Gamestudio Links
Zorro Links
Newest Posts
ZorroGPT
by TipmyPip. 11/19/25 10:10
MRC.c and WFO
by 11honza11. 11/18/25 15:22
webGL
by Ice2642. 11/17/25 21:27
Camera always moves upwards?
by NeoDumont. 11/17/25 09:56
Future of ZorroHFT
by TipmyPip. 11/16/25 13:52
COT Download with Quandl does not work
by Petra. 11/15/25 09:35
Training with the R bridge does not work
by Petra. 11/15/25 09:31
Zorro 2.70
by jcl. 11/15/25 08:43
AUM Magazine
Latest Screens
Rocker`s Revenge
Stug 3 Stormartillery
Iljuschin 2
Galactic Strike X
Who's Online Now
1 registered members (TipmyPip), 32,707 guests, and 5 spiders.
Key: Admin, Global Mod, Mod
Newest Members
SkinnyApe, tritom, sheliepaley, Blueguy, blobplayintennis
19179 Registered Users
Previous Thread
Next Thread
Print Thread
Rate Thread
Page 12 of 12 1 2 10 11 12
Empirical Analysis of Asset Prices [Re: TipmyPip] #488964
11/08/25 22:28
11/08/25 22:28
Joined: Sep 2017
Posts: 174
TipmyPip Online OP
Member
TipmyPip  Online OP
Member

Joined: Sep 2017
Posts: 174
What are “Shiller equations”?

Present-value model & variance bounds: Price equals the discounted stream of expected future payouts. Under rational expectations, the variance of price can’t exceed the variance of the discounted-cash-flow process; Shiller showed stock prices are too volatile relative to this bound (“Do Stock Prices Move Too Much…”, AER 1981).
American Economic Association

Campbell–Shiller log-linear identity: A log-linearization of the present-value model links the log dividend-price ratio to expected future returns and dividend growth, yielding testable decompositions widely used in asset-pricing.
Stern School of Business


Key PDFs (authoritative):

Shiller (1981) AER — “Do Stock Prices Move Too Much to be Justified by Subsequent Changes in Dividends?” (classic variance-bounds test).
American Economic Association

Campbell & Shiller (1988, RFS/NBER) — “The Dividend-Price Ratio and Expectations of Future Dividends and Discount Factors” (log-linear present-value relation).
Stern School of Business


Nobel Prize 2013 press release (PDF) — award to Fama, Hansen, Shiller “for their empirical analysis of asset prices.”
NobelPrize.org


Shiller’s Nobel Prize lecture (PDF): “Speculative Asset Prices.”
NobelPrize.org

Nobel “Popular Science” background (PDF): “Trendspotting in asset markets.”
NobelPrize.org


Code
// ============================================================================
// Shiller_EURUSD.c  —  Zorro / lite-C demonstration script (EUR/USD)
// ============================================================================
// GOAL
// -----
// This script illustrates two classic ideas often discussed in the
// 'variance bounds' / 'dividend–price ratio' (dp) literature:
//
//   Part A) An *illustrative* check of "excess volatility":
//           compare the variance of price P_t to a discounted-sum proxy P*_t
//           constructed from a toy 'dividend' series D_t (here: carry proxy).
//
//   Part B) A very simple *return predictability* example using the
//           dividend-price ratio dp_t := log(D_t / P_t) to predict future
//           K-day returns via a rolling univariate OLS slope.
//
// NOTES (Zorro / lite-C specifics)
// --------------------------------
// • This is a research demo; it trades with a minimal rule only to show how to
//   translate a scalar signal into actions. It is *not* a strategy.
// • Positive series index in Zorro points to the PAST. Example: X[1] is
//   the previous bar, X[K] is K bars ago; X[0] is the current bar.
// • `vars` are rolling series returned by `series(...)`; `var` is a scalar.
// • `asset("EUR/USD")` selects the EUR/USD symbol defined by your asset list.
// • `Lots` is set to 1 purely for a visible action in Part B.
//
// SAFETY / ROBUSTNESS
// -------------------
// • We clamp denominators with a small epsilon to avoid log(0) or division by 0.
// • Window sizes and horizons are explicitly checked against LookBack and Bar.
//
// VERSION
// -------
// Tested with Zorro 2.x / lite-C syntax.
// ============================================================================

function run()
{
    // ------------------------------------------------------------------------
    // SESSION / DATA SETTINGS
    // ------------------------------------------------------------------------
    BarPeriod = 1440;      // 1440 minutes = 1 day bars
    StartDate = 2010;      // start year (use your data span)
    LookBack  = 600;       // bars held in rolling series (must cover max windows)
    asset("EUR/USD");
    set(PLOTNOW);          // auto-plot series as they are produced

    // ------------------------------------------------------------------------
    // PRICE SERIES
    // ------------------------------------------------------------------------
    // P_t: close price; R1: 1-bar (1-day) log return (not used later, kept for ref)
    vars P  = series(priceClose());           // P[0]=today, P[1]=yesterday, ...
    vars R1 = series(log(P[0]/P[1]));         // ln(P_t / P_{t-1})

    // ------------------------------------------------------------------------
    // "DIVIDEND" PROXY D_t  (here: a constant carry series for demonstration)
    // ------------------------------------------------------------------------
    // In FX, a carry-like proxy could be the interest rate differential.
    // Here we just set a constant daily carry to mimic ~1.5% per annum.
    var  eps        = 1e-12;                  // small epsilon for safe divisions
    var  carryDaily = 0.015/252.;             // ? 1.5% p.a. / 252 trading days
    vars D          = series(carryDaily);     // D_t aligned with bars

    // =========================================================================
    // PART A: "Ex post" discounted-sum proxy P*_t for an excess-volatility check
    // =========================================================================
    // Construct a simple discounted sum of past D_t as a toy P*_t proxy:
    //     P*_t ? ?_{k=1..Kmax} D_{t-k} / (1+r_d)^k
    // This is ONLY an illustration, not a proper present-value model.
    int   Kmax = 126;                          // look-back horizon (~6 months)
    var   r_d  = 0.0001;                       // daily discount ? 0.01% (~2.5% p.a.)
    vars  Px   = series(0);                    // rolling proxy P*_t

    if (Bar > LookBack)
    {
        // Build discounted sum from *past* values of D (D[1]..D[Kmax])
        var sumDisc = 0;
        var disc    = 1;
        int k;
        for (k=1; k<=Kmax; k++)
        {
            disc   /= (1 + r_d);               // (1+r)^(-k)
            var Dp  = D[k];                    // D_{t-k}
            sumDisc += disc * Dp;
        }
        Px[0] = sumDisc;                       // write current P*_t proxy

        // Compare rolling variances of P and P* over a window W
        int W = 500;
        if (Bar > LookBack + Kmax + W)
        {
            // Means
            var meanP = 0, meanPx = 0;
            int i;
            for (i=0; i<W; i++) { meanP += P[i]; meanPx += Px[i]; }
            meanP  /= (var)W;
            meanPx /= (var)W;

            // Sample variances
            var varP = 0, varPx = 0;
            for (i=0; i<W; i++) {
                var a = P[i]-meanP;
                var b = Px[i]-meanPx;
                varP  += a*a;
                varPx += b*b;
            }
            varP  /= (var)(W-1);
            varPx /= (var)(W-1);

            // Plots for visual inspection
            plot("Var(P)",  varP,  NEW, 0);
            plot("Var(P*)", varPx, 0,   0);

            // Console line every ~50 bars
            if (Bar%50==0)
                printf("\n[EXCESS VOL] W=%d Var(P)=%.6g Var(P*)=%.6g ratio=%.3f",
                       W, varP, varPx, varP/(varPx+eps));
        }
    }

    // =========================================================================
    // PART B: Return predictability via the dividend-price ratio, dp_t
    // =========================================================================
    // We compute:
    //   dp_t := log(D_t / P_t)
    // and regress *past* K-day realized returns on dp over a rolling window Wreg
    // to estimate a slope 'beta'. A positive beta implies higher dp predicts
    // higher future returns (in this toy setup).
    //
    // Then we convert the instantaneous dp z-score into a small long/short
    // trade signal, clipped and scaled to the range [-0.5, +0.5] (Lev).
    int   K   = 20;                                            // horizon (~1 month)
    vars  DP  = series(log(max(eps, D[0]) / max(eps, P[0])));  // dp_t series
    vars  RK  = series(log(P[0]/P[K]));                        // realized K-day return

    int   Wreg = 500;                                          // regression window
    if (Bar > LookBack + K + Wreg)
    {
        // ----------------------------
        // Rolling univariate OLS slope
        // ----------------------------
        var sumX=0, sumY=0, sumXX=0, sumXY=0;
        int i;
        for (i=0;i<Wreg;i++){
            var x = DP[i];     // predictor
            var y = RK[i];     // response (past K-day return)
            sumX  += x;
            sumY  += y;
            sumXX += x*x;
            sumXY += x*y;
        }
        var meanX = sumX/Wreg;
        var meanY = sumY/Wreg;
        var denom = sumXX - Wreg*meanX*meanX;

        var beta = 0;                                         // OLS slope
        if (denom != 0)
            beta = (sumXY - Wreg*meanX*meanY)/denom;

        plot("beta(dp->Kret)", beta, NEW, 0);

        // ----------------------------
        // z-score of current dp_t
        // ----------------------------
        var meanDP=0, varDP=0;
        for (i=0;i<Wreg;i++) meanDP += DP[i];
        meanDP/=Wreg;
        for (i=0;i<Wreg;i++){ var d=DP[i]-meanDP; varDP += d*d; }
        varDP /= (Wreg-1);
        var sDP  = sqrt(max(eps,varDP));
        var zDP  = (DP[0]-meanDP)/sDP;

        // Clip z to avoid huge outliers
        var zClip = zDP;
        if (zClip >  2) zClip =  2;
        if (zClip < -2) zClip = -2;

        // Direction follows beta sign
        var sig = 0;
        if (beta > 0)      sig = zClip;
        else if (beta < 0) sig = -zClip;

        // ----------------------------
        // POSITION TRANSLATION
        // ----------------------------
        // Map raw signal in [-2,+2] to leverage-like knob in [-1,+1],
        // then cap at ±0.5 to keep actions small in the demo.
        var Target = sig;          // raw -2..+2
        var MaxLev = 0.5;          // clamp bound
        var Lev    = Target/2.0;   // scale to -1..+1 then cap
        if (Lev >  MaxLev) Lev =  MaxLev;
        if (Lev < -MaxLev) Lev = -MaxLev;

        // Minimal action rule:
        // if Lev is meaningfully positive => long; if negative => short; else flat.
        // We keep Lots=1 for visibility; no money management here.
        if (Lev > 0.05) { exitShort(); enterLong();  Lots = 1; }
        else if (Lev < -0.05) { exitLong(); enterShort(); Lots = 1; }
        else { exitLong(); exitShort(); }

        // Plots for monitoring
        plot("z(dp)", zDP, 0, 0);
        plot("lev",  Lev,  0, 0);
    }

    // End of run() — Zorro handles bar stepping automatically.
}

Attached Files
Shiller_EURUSD.zip (9 downloads)
Empirical Analysis of Asset Prices (with NN) [Re: TipmyPip] #488965
11/09/25 08:39
11/09/25 08:39
Joined: Sep 2017
Posts: 174
TipmyPip Online OP
Member
TipmyPip  Online OP
Member

Joined: Sep 2017
Posts: 174
the strategy encodes the Campbell–Shiller insight that high dividend/“carry” yields relative to price predict higher future returns, wraps that valuation in a z-scored
????????????, and lets a linear neural unit blend it with momentum/volatility states to produce directional edge; trades are taken when the learned edge clears a small threshold.

Code
// ============================================================================
// Shiller NN EUR/USD — ML trading demo (Zorro / lite-C)
//
// • Learner: PERCEPTRON (+BALANCED) on a compact 8-feature vector.
// • Trigger: edge = predL - predS with a simple RSI + momentum fallback.
// • Plots: (name, value, color, style); panels anchored correctly.
// ============================================================================

#include <default.c>

// ===== Configuration =====
#define LOOKBACK   200     // Bars required before running the model/logic
#define BarMins    1440    // Daily bars
#define LotsFixed  1       // Position size per entry
#define EdgeMin    0.05    // ML edge threshold (predL - predS) to trigger a trade

// ===== Safe helpers =====
var safe_div(var a, var b)
{
  if (invalid(a) || invalid(b) || b == 0) return 0;
  return a/b;
}

var safe_logratio(var a, var b)
{
  if (invalid(a) || invalid(b) || b == 0) return 0;
  var r = a/b;
  if (invalid(r) || r <= 0) return 0;
  return log(r);
}

// NOTE: plot(name, value, color, style)
// We'll pass color first, then style flags (e.g., LINE, NEW, MAIN, etc.)
void plot_safe(string name, var v, int color, int style)
{
  if (!invalid(v) && v > -1e-12 && v < 1e12)
    plot(name, v, color, style);
}

// ===== Main strategy =====
function run()
{
  // Session (file-free; no RULES ? no rule files created/loaded)
  StartDate = 2010;
  EndDate   = 2025;
  BarPeriod = BarMins;
  LookBack  = LOOKBACK;
  Capital   = 10000;
  set(PARAMETERS|PLOTNOW);
  Hedge = 0;
  asset("EUR/USD");

  // Base series
  vars PC = series(priceClose());  // Close series for returns/momentum
  vars PX = series(price());       // Price series for RSI

  // Derived series (allocated once, updated every bar)
  static vars R1;     if (!R1)    R1    = series(0);  // 1-bar log return
  static vars MOM5;   if (!MOM5)  MOM5  = series(0);  // 5-bar momentum
  static vars MOM20;  if (!MOM20) MOM20 = series(0);  // 20-bar momentum
  static vars DP;     if (!DP)    DP    = series(0);  // dp proxy = log(D/P)

  if (Bar > 0)  R1[0]    = safe_logratio(PC[0], PC[1]);   else R1[0]    = 0;
  if (Bar > 5)  MOM5[0]  = safe_logratio(PC[0], PC[5]);   else MOM5[0]  = 0;
  if (Bar > 20) MOM20[0] = safe_logratio(PC[0], PC[20]);  else MOM20[0] = 0;

  // Constant carry vs price ? dp_t = log(D_t / P_t) (simple demonstration proxy)
  var carryDaily = 0.015/252.;  // ~1.5% p.a.
  if (Bar > 0) DP[0] = safe_logratio(carryDaily, PC[0]); else DP[0] = 0;

  // Indicators with warmup guards
  var vola  = 0;  if (Bar >= 21) vola  = StdDev(R1, 20);
  var atr20 = 0;  if (Bar >= 21) atr20 = ATR(20);
  var rsi14 = 50; if (Bar >= 15) rsi14 = RSI(PX, 14);

  // dp z-score (window Wz)
  var zDP = 0; int Wz = 500;
  if (Bar >= Wz) {
    int i; var mean = 0, s2 = 0;
    for (i = 0; i < Wz; i++) mean += DP[i];
    mean /= (var)Wz;
    for (i = 0; i < Wz; i++) { var d = DP[i] - mean; s2 += d*d; }
    var sd = sqrt(max(1e-12, s2/(Wz - 1)));
    if (sd > 0) {
      zDP = (DP[0] - mean) / sd;
      if (zDP >  10) zDP =  10;
      if (zDP < -10) zDP = -10;
    }
  }

  if (Bar < LOOKBACK) {
    // Anchor price panel early so the chart opens immediately
    plot_safe("Close", priceClose(), 0, MAIN|LINE);
    return;
  }

  // Feature vector (?20)
  var F[8];
  F[0] = zDP;
  F[1] = MOM5[0];
  F[2] = MOM20[0];
  F[3] = vola;
  F[4] = rsi14/100.;
  F[5] = safe_div(atr20, PC[0]);
  F[6] = R1[0];
  F[7] = safe_logratio(PC[0], PC[10]);

  // Built-in ML (file-free: no RULES)
  var predL = adviseLong (PERCEPTRON + BALANCED, 0, F, 8);
  var predS = adviseShort(PERCEPTRON + BALANCED, 0, F, 8);

  // Trading logic: edge trigger with simple fallback
  var edge = predL - predS;
  Lots = LotsFixed;

  int didTrade = 0;
  if (!invalid(edge) && edge > EdgeMin) {
    exitShort(); enterLong();  didTrade = 1;
  } else if (!invalid(edge) && edge < -EdgeMin) {
    exitLong();  enterShort(); didTrade = 1;
  }

  if (!didTrade) {
    if (rsi14 > 55 && MOM5[0] > 0) { exitShort(); enterLong();  didTrade = 1; }
    else if (rsi14 < 45 && MOM5[0] < 0) { exitLong(); enterShort(); didTrade = 1; }
    else { exitLong(); exitShort(); }
  }

  // ===== Plots (color, style) =====
  // Price on the main chart
  plot_safe("Close", priceClose(), 0, MAIN|LINE);

  // Open a NEW indicator panel with 'edge', then add other lines to the same panel
  plot_safe("edge",  edge,  0, NEW|LINE);   // NEW opens the panel
  plot_safe("predL", predL, 0, LINE);
  plot_safe("predS", predS, 0, LINE);
  plot_safe("RSI",   rsi14, 0, LINE);
  plot_safe("z(dp)", zDP,   0, LINE);
}



A walkford version :

Code
// ============================================================================
// BLA03x10_WFO_train_test.c
// EUR/USD — Single-script ML trading with explicit Train/Test separation.
// Zorro / lite-C
//
// • Train run (click “Train”): writes per-cycle RULE files (no TESTNOW).
// • Test/Trade run (click “Test” or “Trade”): loads the RULE files created in Train.
// • Learner: PERCEPTRON + BALANCED 
// • WFO supported via NumWFOCycles + DataHorizon (same in Train & Test).
// • Consistent asset() + algo() + advise* signature in both phases.
// • No ternary operator; guarded indicators; compact 8-feature vector.
// ============================================================================

#include <default.c>

// ===== Switches / Knobs =====
#define USE_WFO         1        // 0 = single IS block; 1 = Walk-Forward (IS/OOS cycles)
#define WFO_CYCLES      6        // number of WFO cycles (Train & Test must match)
#define WFO_OOS_BARS    252      // OOS length per cycle in bars (daily ? 1y)

#define LOOKBACK        200      // warmup bars before any model/logic
#define BarMins         1440     // 1D bars
#define LotsFixed       1        // fixed position size
#define EdgeMin         0.05     // edge = predL - predS threshold

// ===== Safe helpers =====
var safe_div(var a,var b){ if(invalid(a)||invalid(b)||b==0) return 0; return a/b; }
var safe_logratio(var a,var b){
  if(invalid(a)||invalid(b)||b==0) return 0;
  var r=a/b; if(invalid(r)||r<=0) return 0; return log(r);
}
// plot(name, value, color, style)
void plot_safe(string n, var v, int c, int s){ if(!invalid(v)&&v>-1e12&&v<1e12) plot(n,v,c,s); }

// ===== Main =====
function run()
{
  // -------- Session (identical in Train and Test except RULES/Hedge flags) --------
  StartDate = 2010;
  EndDate   = 2025;
  BarPeriod = BarMins;
  LookBack  = LOOKBACK;
  Capital   = 10000;

  if(USE_WFO){
    NumWFOCycles = WFO_CYCLES;
    DataHorizon  = WFO_OOS_BARS;         // OOS size per cycle
  } else {
    NumWFOCycles = 1;
    DataHorizon  = 0;
  }

  set(PARAMETERS|PLOTNOW);               // common flags

  // Explicit Train/Test separation (no TESTNOW auto phase switching)
  if(Train){
    set(RULES);                          // write RULE files during Train only
    Hedge = 2;                           // generate both L/S samples while training
  } else {
    Hedge = 0;                           // Test/Trade loads RULE files, no writing
  }

  asset("EUR/USD");
  algo("dp");                            // part of RULE key: <Asset>:<Algo>:<L|S>

  // -------- Base series --------
  vars PC = series(priceClose());        // close for returns/momentum
  vars PX = series(price());             // price for RSI

  // -------- Derived series (allocated once, updated every bar) --------
  static vars R1;     if(!R1)    R1    = series(0);  // 1-bar log return
  static vars MOM5;   if(!MOM5)  MOM5  = series(0);  // 5-bar log momentum
  static vars MOM20;  if(!MOM20) MOM20 = series(0);  // 20-bar log momentum
  static vars DP;     if(!DP)    DP    = series(0);  // dp proxy = log(D/P)

  if(Bar > 0)  R1[0]    = safe_logratio(PC[0],PC[1]);  else R1[0]    = 0;
  if(Bar > 5)  MOM5[0]  = safe_logratio(PC[0],PC[5]);  else MOM5[0]  = 0;
  if(Bar > 20) MOM20[0] = safe_logratio(PC[0],PC[20]); else MOM20[0] = 0;

  var carryDaily = 0.015/252.;
  if(Bar > 0) DP[0] = safe_logratio(carryDaily, PC[0]); else DP[0] = 0;

  // -------- Indicators with guards --------
  var vola  = 0;  if(Bar >= 21) vola  = StdDev(R1,20);
  var atr20 = 0;  if(Bar >= 21) atr20 = ATR(20);
  var rsi14 = 50; if(Bar >= 15) rsi14 = RSI(PX,14);

  // -------- dp z-score (window Wz) --------
  var zDP = 0; int Wz = 500;
  if(Bar >= Wz){
    int i; var mean=0, s2=0;
    for(i=0;i<Wz;i++) mean += DP[i];
    mean /= (var)Wz;
    for(i=0;i<Wz;i++){ var d = DP[i]-mean; s2 += d*d; }
    var sd = sqrt(max(1e-12, s2/(Wz-1)));
    if(sd > 0){
      zDP = (DP[0]-mean)/sd;
      if(zDP > 10)  zDP = 10;
      if(zDP < -10) zDP = -10;
    }
  }

  // Anchor main panel early
  if(Bar < LOOKBACK){
    plot_safe("Close", priceClose(), BLACK, MAIN|LINE);
    return;
  }

  // -------- Feature vector (? 20) --------
  var F[8];
  F[0] = zDP;
  F[1] = MOM5[0];
  F[2] = MOM20[0];
  F[3] = vola;
  F[4] = rsi14/100.;
  F[5] = safe_div(atr20, PC[0]);
  F[6] = R1[0];
  F[7] = safe_logratio(PC[0], PC[10]);

  // -------- Built-in ML calls (IDENTICAL in Train & Test) --------
  // Important: same method flags, same slot number, same feature length & order,
  // same asset() and algo() ? ensures matching rule keys and file names.
  var predL = adviseLong (PERCEPTRON + BALANCED, 0, F, 8);
  var predS = adviseShort(PERCEPTRON + BALANCED, 0, F, 8);

  // -------- Execution logic (common) --------
  var edge = predL - predS;
  Lots = LotsFixed;

  int didTrade = 0;
  if(!invalid(edge) && edge > EdgeMin){ exitShort(); enterLong();  didTrade = 1; }
  else if(!invalid(edge) && edge < -EdgeMin){ exitLong(); enterShort(); didTrade = 1; }

  if(!didTrade){
    if(rsi14 > 55 && MOM5[0] > 0) { exitShort(); enterLong();  didTrade = 1; }
    else if(rsi14 < 45 && MOM5[0] < 0) { exitLong(); enterShort(); didTrade = 1; }
    else { exitLong(); exitShort(); }
  }

  // -------- Plots --------
  plot_safe("Close", priceClose(), BLACK, MAIN|LINE);
  plot_safe("edge",  edge,  GREEN, NEW|LINE);
  plot_safe("predL", predL, BLUE,  LINE);
  plot_safe("predS", predS, RED,   LINE);
  plot_safe("RSI",   rsi14, 0x404040, LINE);
  plot_safe("z(dp)", zDP,   0x800080, LINE);
}

Attached Files
MShillerNN_EURUSD.zip (12 downloads)
Last edited by TipmyPip; 11/09/25 11:26.
Re: Empirical Analysis of Asset Prices (with NN) [Re: TipmyPip] #488966
11/10/25 11:04
11/10/25 11:04
Joined: Sep 2017
Posts: 174
TipmyPip Online OP
Member
TipmyPip  Online OP
Member

Joined: Sep 2017
Posts: 174
I have a question for all my Dear fellow programmers, If you had a book of one single strategy, 500 pages, explaining with detailed descriptions how to develop and come about complex strategies, how much would you be willing to pay for a copy of the book?

Thank you for your attention, and thoughtful consideration?

SAR MOMENTUM BOT [Re: TipmyPip] #488982
3 hours ago
3 hours ago
Joined: Sep 2017
Posts: 174
TipmyPip Online OP
Member
TipmyPip  Online OP
Member

Joined: Sep 2017
Posts: 174
This script is a Zorro trading strategy that trades EUR/USD on 5-minute bars using the Parabolic SAR for direction and an optional momentum filter:


It optimizes five core parameters: SAR_STEP (SAR sensitivity), DRAW_BEFORE_SL_POINTS (how far price must move against you before a delayed stop is placed),
STOP_POINTS (fixed stop-loss in pips), TAKEPROFIT_POINTS (fixed take-profit in pips),MAX_HOLD_BARS (maximum number of bars a trade may stay open).

On each bar it:

Computes SAR and recent price movement. Generates long/short signals based on whether SAR is below or above price, refined by momentum and basic filters (spread, session, news stubs).
Closes trades either when an opposite SAR signal appears or when they exceed MAX_HOLD_BARS.
Opens 1-lot market orders (no position sizing logic yet) with the optimized SL/TP and uses SarTMF to apply a delayed stop-loss once the trade has moved against you by a configurable amount.
It also logs detailed per-bar info to GoldSarDebug.csv for debugging and analysis.

With a little creative mind this one can improve alot.


Code
// ======================================================
//  SAR MOMENTUM BOT
//  SAR direction entries, optional momentum filter,
//  + optimizable SAR step / delayed SL / StopLoss / TakeProfit / Max holding time
// ======================================================

#include <default.c>
#include <stdio.h>   // for file-based debug logging

//------------------------------------------------------//
//  USER PARAMETERS (defaults – some are overwritten by optimize())
//------------------------------------------------------//

// Bar timeframe for SAR etc. (minutes)
int      TRADE_TIMEFRAME      = 5;       // M5

// Parabolic SAR params (Zorro SAR(Step,Min,Max))
var      SAR_STEP             = 0.02;
var      SAR_MAX              = 0.20;
var      SAR_MIN              = 0.02;    // usually same as step

// Distance from price for pending order (in pips)
int      SAR_BUFFER_POINTS    = 25;

// Trading session
int      USE_GMT_TIME         = 1;       // (unused – hour(0) is used)
int      SESSION_START_HOUR   = 7;       // 0..23
int      SESSION_END_HOUR     = 21;      // 0..23

// News filter (stub – always off unless implemented)
int      USE_NEWS_FILTER      = 0;

// Lot size modes
#define LOT_FIXED_LOT         0
#define LOT_BALANCE_PERCENT   1
#define LOT_EQUITY_PERCENT    2
#define LOT_FIXED_RISK_MONEY  3

int      LotMode            = LOT_BALANCE_PERCENT;
var      FIXED_LOT_SIZE     = 0.10;
var      RISK_PERCENT       = 0.5;     // for BALANCE/EQUITY
var      FIXED_RISK_MONEY   = 50.0;    // account currency

// Momentum filter window (seconds)
int      ACTIVATE_WINDOW_SEC  = 900;   // default ~15 minutes
int      ACTIVATE_MOVE_POINTS = 10;    // min move in window (pips)

// Pending expiry / staleness windows (seconds)
int      PENDING_EXPIRE_SEC   = 30;   // hard life of pending (unused with market)
int      STALE_WINDOW_SEC     = 15;   // after this, require min move
int      STALE_MOVE_POINTS    = 30;   // else cancel

// Delayed stop-loss (used only by TMF when Stop==0)
int      DRAW_BEFORE_SL_POINTS  = 60;  // move against trade before SL is drawn
int      EXTRA_SL_BUFFER_POINTS = 25;  // SL extra buffer beyond current price

// Concurrency & spread
int      MAX_CONCURRENT_ORDERS  = 1;   // informational only
var      MAX_SPREAD_POINTS      = 20;  // in pips

// Explicit exits (in pips, will be converted to price units by *PIP)
// THESE THREE + SAR_STEP + DRAW_BEFORE_SL_POINTS ARE OPTIMIZED
int      STOP_POINTS            = 40;   // fixed SL in pips
int      TAKEPROFIT_POINTS      = 60;   // fixed TP in pips
int      MAX_HOLD_BARS          = 72;   // max bars a trade can stay open

//------------------------------------------------------//
//  INTERNAL STATE
//------------------------------------------------------//

#define HISTORY_SIZE 200

var   PriceHistory[HISTORY_SIZE];   // tick Bid approximation
var   TimeHistory[HISTORY_SIZE];    // windows DATE stamps
var   SpreadHistory[HISTORY_SIZE];  // spread in pips

// Last SAR value (updated per bar in run())
var   SarValue = 0;

// Optional status text for UI / debugging
string RestrictionReason = "";

// small debug switch (set to 1 if you want printf logs)
int    DEBUG_LOG = 0;

// debug counter: how many times entry conditions were true
int    EntrySignalCount = 0;

// helper switches for backtest
int    RELAX_FILTERS_FOR_BACKTEST      = 1;  // 1 = no spread/session/momentum/news blocking
int    USE_MARKET_ORDERS_FOR_BACKTEST  = 1;  // 1 = Entry=0 (market), 0 = pending stops

// file-based debug logging
FILE*  DebugFile = 0;       // will write GoldSarDebug.csv

//------------------------------------------------------//
//  FORWARD DECLARATIONS
//------------------------------------------------------//

void  ShiftHistoryArrays();
int   IsWithinTradingSession();
int   IsNewsTime();
void  ComputeRecentMove(var nowDate, int windowSec, var *pMaxUp, var *pMaxDown);
int   CountAllOrdersForThisEA();
int   NotExistingPendingBuyStop();
int   NotExistingPendingSellStop();
var   ComputeLotSize(int mode, var riskPercent, var fixedRiskMoney, var fixedLot, int stopPoints);
var   NormalizeLot(var lot);

// Trade management function: delayed SL + pending expiry/staleness
int   SarTMF(var placementDate);

// we'll call tick() from run()
void  tick();

// debug logging helper
void  LogDebugState(var nowDate, var barPrice, var spreadPips,
                    var moveUp, var moveDown,
                    int sarBelowBar, int sarAboveBar,
                    int longSignal, int shortSignal,
                    var lotsLogged);

//------------------------------------------------------//
//  INIT & MAIN BAR LOOP
//------------------------------------------------------//

function run()
{
	// enable optimization & log file (same idea as the simple script)
	set(PARAMETERS + LOGFILE);

	// global test / bar settings
	BarPeriod = TRADE_TIMEFRAME;  // e.g. 5-minute bars
	StartDate = 2005;             // adjust as you like
	EndDate   = 0;
	LookBack  = 200;

	// select the asset exactly as in the simple script
	asset("EUR/USD");

	// one-time initialization stuff
	if (is(INITRUN)) 
	{
		// init histories
		int i;
		for (i = 0; i < HISTORY_SIZE; i++) {
			PriceHistory[i]  = 0;
			TimeHistory[i]   = 0;
			SpreadHistory[i] = 0;
		}

		RestrictionReason = "INIT";

		// open debug CSV (overwrite each run)
		DebugFile = fopen("GoldSarDebug.csv","w");
		if (DebugFile) {
			fprintf(DebugFile,"Bar;Date;Price;SAR;SpreadPips;MoveUp;MoveDown;");
			fprintf(DebugFile,"SarBelowBar;SarAboveBar;LongSignal;ShortSignal;TotalOrders;LotMode;Lots;RestrictionReason\n");
			fflush(DebugFile);
		}
	}

	// EXITRUN cleanup
	if (is(EXITRUN)) {
		if (DEBUG_LOG)
			printf("\nExitRun: EntrySignalCount = %d",EntrySignalCount);
		if (DebugFile) {
			fclose(DebugFile);
			DebugFile = 0;
		}
		return;
	}

	//--------------------------------------------------
	// OPTIMIZED PARAMETERS (5 params total)
	//  1) SAR_STEP              – SAR sensitivity
	//     (SAR_MIN follows it)
	//  2) DRAW_BEFORE_SL_POINTS – distance before delayed SL activates
	//  3) STOP_POINTS           – fixed SL in pips
	//  4) TAKEPROFIT_POINTS     – fixed TP in pips
	//  5) MAX_HOLD_BARS         – max bar age of trade
	//--------------------------------------------------

	// 1 – SAR step (0.01 .. 0.06, step 0.01)
	SAR_STEP = optimize(0.02, 0.01, 0.06, 0.01);
	SAR_MIN  = SAR_STEP;       // tie min to step
	// SAR_MAX stays fixed at 0.20

	// 2 – delayed SL activation distance (20..120 pips, step 10)
	DRAW_BEFORE_SL_POINTS = (int)optimize(60, 20, 120, 10);

	// 3 – Fixed SL in pips (20..120, step 10)
	STOP_POINTS = (int)optimize(40, 20, 120, 10);

	// 4 – Fixed TP in pips (20..240, step 20)
	TAKEPROFIT_POINTS = (int)optimize(60, 20, 240, 20);

	// 5 – Max holding time in bars (24..288, step 24)
	MAX_HOLD_BARS = (int)optimize(72, 24, 288, 24);

	//--------------------------------------------------
	// INDICATORS (bar-based)
	//--------------------------------------------------

	// Compute current SAR on bar data (one SAR series)
	SarValue = SAR(SAR_STEP, SAR_MIN, SAR_MAX);

	// Let tick() handle trade logic
	tick();
}

//------------------------------------------------------//
//  TICK-BASED MAIN LOGIC (per incoming bar)
//------------------------------------------------------//

function tick()
{
	asset("EUR/USD");

	// ------------------------------
	// Mid price and spread
	// ------------------------------
	var mid = price();        // bar price (close)

	// Zorro's Spread is in pips for FX
	var spreadPips  = Spread;          // pips
	var spreadPrice = spreadPips*PIP;  // convert to price units

	// Approximate Bid/Ask from mid and spread in price units
	var bid = mid - 0.5*spreadPrice;
	var ask = mid + 0.5*spreadPrice;

	// Also keep a direct "price" for SAR comparison
	var barPrice = mid;

	// Current time in DATE format
	var nowDate = wdate(0);   // current bar time in Windows DATE

	// Update history (always, even during warmup)
	ShiftHistoryArrays();
	PriceHistory[0]  = bid;
	TimeHistory[0]   = nowDate;
	SpreadHistory[0] = spreadPips;

	// momentum & signal variables
	var moveUp = 0, moveDown = 0;
	int sarBelowBar = 0, sarAboveBar = 0;
	int longSignal = 0, shortSignal = 0;

	// ------------------------------
	// WARMUP: fill history & SAR first
	// ------------------------------
	if (Bar < LookBack) {
		RestrictionReason = "Warming up history";
		LogDebugState(nowDate, barPrice, spreadPips,
			0, 0, 0, 0, 0, 0, 0);
		return;
	}

	// ------------------------------
	// TIME EXIT: close trades that are too old
	// ------------------------------
	if (MAX_HOLD_BARS > 0 && (NumOpenLong > 0 || NumOpenShort > 0)) {
		int needExit = 0;
		for (open_trades) {
			int ageBars = Bar - TradeBarOpen;
			if (ageBars >= MAX_HOLD_BARS) {
				needExit = 1;
				// IMPORTANT FIX: use break_trades instead of plain break
				break_trades;
			}
		}
		if (needExit) {
			exitLong();
			exitShort();
		}
	}

	// recalc orders after possible time exits
	int totalOrders = CountAllOrdersForThisEA();

	// precompute SAR vs bar price for logging & signals
	sarBelowBar = (SarValue < barPrice);
	sarAboveBar = (SarValue > barPrice);

	// ------------------------------
	// BASIC FILTERS: SPREAD / SESSION / NEWS
	// ------------------------------	
	if (!RELAX_FILTERS_FOR_BACKTEST && spreadPips > MAX_SPREAD_POINTS) {
		RestrictionReason = "Spread too high";
		LogDebugState(nowDate, barPrice, spreadPips,
			moveUp, moveDown, sarBelowBar, sarAboveBar, 0, 0, 0);
		return;
	}

	if (!RELAX_FILTERS_FOR_BACKTEST && !IsWithinTradingSession()) {
		RestrictionReason = "Outside trading session";
		LogDebugState(nowDate, barPrice, spreadPips,
			moveUp, moveDown, sarBelowBar, sarAboveBar, 0, 0, 0);
		return;
	}

	if (!RELAX_FILTERS_FOR_BACKTEST && USE_NEWS_FILTER && IsNewsTime()) {
		RestrictionReason = "News filter active";
		LogDebugState(nowDate, barPrice, spreadPips,
			moveUp, moveDown, sarBelowBar, sarAboveBar, 0, 0, 0);
		return;
	}

	RestrictionReason = "OK";

	// ------------------------------
	// MOMENTUM CHECK (bar-based)
	// ------------------------------
	ComputeRecentMove(nowDate, ACTIVATE_WINDOW_SEC, &moveUp, &moveDown);

	if (!RELAX_FILTERS_FOR_BACKTEST && ACTIVATE_MOVE_POINTS > 0) { 
		if (moveUp < ACTIVATE_MOVE_POINTS && fabs(moveDown) < ACTIVATE_MOVE_POINTS) {
			RestrictionReason = "Not enough momentum";
			LogDebugState(nowDate, barPrice, spreadPips,
				moveUp, moveDown, sarBelowBar, sarAboveBar, 0, 0, 0);
			return;
		}
	}

	// ------------------------------
	// SAR VALUE & TREND BIAS
	// ------------------------------
	if (SarValue == 0) {
		RestrictionReason = "SAR unavailable";
		LogDebugState(nowDate, barPrice, spreadPips,
			moveUp, moveDown, sarBelowBar, sarAboveBar, 0, 0, 0);
		return;
	}

	// ------------------------------
	// BUILD SIGNALS (LONG / SHORT)
	// ------------------------------
	longSignal  = sarBelowBar;
	shortSignal = sarAboveBar;

	if (!RELAX_FILTERS_FOR_BACKTEST && ACTIVATE_MOVE_POINTS > 0) {
		if (longSignal && moveUp < ACTIVATE_MOVE_POINTS)
			longSignal = 0;
		if (shortSignal && fabs(moveDown) < ACTIVATE_MOVE_POINTS)
			shortSignal = 0;
	}

	// ------------------------------
	// EXIT LOGIC: flip on opposite SAR signal
	// ------------------------------
	if (NumOpenLong > 0 && shortSignal)
		exitLong();
	if (NumOpenShort > 0 && longSignal)
		exitShort();

	// recalc after flip exits
	totalOrders = CountAllOrdersForThisEA();

	// ------------------------------
	// DEBUG: entry condition monitoring
	// ------------------------------
	if (longSignal) {
		EntrySignalCount++;
		if (DEBUG_LOG) {
			printf("\nBar %d LONG signal: moveUp=%.1f, SAR=%.5f, bid=%.5f, ask=%.5f, barPrice=%.5f",
				Bar, moveUp, SarValue, bid, ask, barPrice);
		}
	}
	if (shortSignal) {
		EntrySignalCount++;
		if (DEBUG_LOG) {
			printf("\nBar %d SHORT signal: moveDown=%.1f, SAR=%.5f, bid=%.5f, ask=%.5f, barPrice=%.5f",
				Bar, moveDown, SarValue, bid, ask, barPrice);
		}
	}

	// ------------------------------
	// PLACE BUY / SELL (market orders in backtest)
	// ------------------------------
	if (totalOrders == 0)
	{
		// Stop / TP in PRICE units
		Stop       = STOP_POINTS       * PIP;
		TakeProfit = TAKEPROFIT_POINTS * PIP;
		Trail      = 0;
		OrderDuration = PENDING_EXPIRE_SEC;

		// BUY
		if (longSignal) {
			int stopPointsB = DRAW_BEFORE_SL_POINTS + EXTRA_SL_BUFFER_POINTS;

			var lotB = 1;
			Lots  = lotB;

			if (USE_MARKET_ORDERS_FOR_BACKTEST)
				Entry = 0;
			else
				Entry = SAR_BUFFER_POINTS; // pips offset if you ever use pending

			if (DEBUG_LOG) {
				printf("\nBar %d  enterLong: Lots=%.2f EntryOffset=%g stopPoints=%d StopPips=%d TPpips=%d",
					Bar, Lots, (var)Entry, stopPointsB, STOP_POINTS, TAKEPROFIT_POINTS);
			}

			enterLong(SarTMF, nowDate);

			LogDebugState(nowDate, barPrice, spreadPips,
				moveUp, moveDown, sarBelowBar, sarAboveBar,
				longSignal, shortSignal, Lots);

			return;
		}

		// SELL
		if (shortSignal) {
			int stopPointsS = DRAW_BEFORE_SL_POINTS + EXTRA_SL_BUFFER_POINTS;

			var lotS = 1;
			Lots  = lotS;

			if (USE_MARKET_ORDERS_FOR_BACKTEST)
				Entry = 0;
			else
				Entry = SAR_BUFFER_POINTS;

			if (DEBUG_LOG) {
				printf("\nBar %d  enterShort: Lots=%.2f EntryOffset=%g stopPoints=%d StopPips=%d TPpips=%d",
					Bar, Lots, (var)Entry, stopPointsS, STOP_POINTS, TAKEPROFIT_POINTS);
			}

			enterShort(SarTMF, nowDate);

			LogDebugState(nowDate, barPrice, spreadPips,
				moveUp, moveDown, sarBelowBar, sarAboveBar,
				longSignal, shortSignal, Lots);

			return;
		}
	}

	// no trade placed on this bar -> log state
	LogDebugState(nowDate, barPrice, spreadPips,
		moveUp, moveDown, sarBelowBar, sarAboveBar,
		0, 0, 0);
}

//------------------------------------------------------//
//  DEBUG LOGGING HELPER
//------------------------------------------------------//

void LogDebugState(var nowDate, var barPrice, var spreadPips,
                   var moveUp, var moveDown,
                   int sarBelowBar, int sarAboveBar,
                   int longSignal, int shortSignal,
                   var lotsLogged)
{
	if (!DebugFile || Bar < LookBack)
		return;

	fprintf(DebugFile,
		"%d;%.6f;%.5f;%.5f;%.1f;%.1f;%.1f;%d;%d;%d;%d;%d;%d;%.2f;%s\n",
		Bar, nowDate, barPrice, SarValue, spreadPips,
		moveUp, moveDown,
		sarBelowBar, sarAboveBar,
		longSignal, shortSignal,
		CountAllOrdersForThisEA(),
		LotMode, lotsLogged,
		RestrictionReason
	);
	fflush(DebugFile);
}

//------------------------------------------------------//
//  HISTORY SHIFT
//------------------------------------------------------//

void ShiftHistoryArrays()
{
	int i;
	for (i = HISTORY_SIZE-1; i > 0; i--) {
		PriceHistory[i]  = PriceHistory[i-1];
		TimeHistory[i]   = TimeHistory[i-1];
		SpreadHistory[i] = SpreadHistory[i-1];
	}
}

//------------------------------------------------------//
//  SESSION FILTER (hour-based)
//------------------------------------------------------//

int IsWithinTradingSession()
{
	if (SESSION_START_HOUR == SESSION_END_HOUR)
		return 1;

	int hourNow = hour(0);   // bar/tick time in BarZone

	if (SESSION_START_HOUR < SESSION_END_HOUR) {
		if (hourNow >= SESSION_START_HOUR && hourNow < SESSION_END_HOUR)
			return 1;
		else
			return 0;
	} else {
		if (hourNow >= SESSION_START_HOUR || hourNow < SESSION_END_HOUR)
			return 1;
		else
			return 0;
	}
}

//------------------------------------------------------//
//  NEWS FILTER – STUB
//------------------------------------------------------//

int IsNewsTime()
{
	if (!USE_NEWS_FILTER)
		return 0;

	return 0;
}

//------------------------------------------------------//
//  RECENT PRICE MOVE (bar-based window derived from seconds)
//------------------------------------------------------//

void ComputeRecentMove(var nowDate, int windowSec, var *pMaxUp, var *pMaxDown)
{
	var maxUp   = 0;
	var maxDown = 0;

	var secondsPerBar = 60*TRADE_TIMEFRAME;      // e.g. 5min -> 300s
	int windowBars = (int)(windowSec / secondsPerBar);
	if (windowBars < 1) windowBars = 1;
	if (windowBars >= HISTORY_SIZE) windowBars = HISTORY_SIZE-1;

	var refPrice = PriceHistory[0];

	int i;
	for (i = 1; i <= windowBars; i++) {
		if (PriceHistory[i] == 0)
			continue;

		var deltaPoints = (refPrice - PriceHistory[i]) / PIP; // in pips

		if (deltaPoints > maxUp)
			maxUp = deltaPoints;
		if (deltaPoints < maxDown)
			maxDown = deltaPoints;
	}

	*pMaxUp   = maxUp;
	*pMaxDown = maxDown;
}

//------------------------------------------------------//
//  LOT SIZE CALCULATION (using PIPCost)
//------------------------------------------------------//

var ComputeLotSize(int mode,
                   var riskPercent,
                   var fixedRiskMoney,
                   var fixedLot,
                   int stopPoints)
{
	if (stopPoints <= 0) {
		return NormalizeLot(fixedLot);
	}

	var riskPerLotMoney = stopPoints * PIPCost;
	var lot;

	if (mode == LOT_FIXED_LOT) {
		lot = fixedLot;
	} 
	else if (mode == LOT_BALANCE_PERCENT) {
		var accBal = Balance;
		var maxRiskMoney = accBal * (riskPercent/100.);
		lot = maxRiskMoney / riskPerLotMoney;
	} 
	else if (mode == LOT_EQUITY_PERCENT) {
		var accEq  = Equity;
		var maxRiskMoney = accEq * (riskPercent/100.);
		lot = maxRiskMoney / riskPerLotMoney;
	} 
	else if (mode == LOT_FIXED_RISK_MONEY) {
		lot = fixedRiskMoney / riskPerLotMoney;
	} 
	else {
		lot = fixedLot;
	}

	return NormalizeLot(lot);
}

//------------------------------------------------------//
//  LOT NORMALIZATION – basic integer clipping
//------------------------------------------------------//

var NormalizeLot(var lot)
{
	if (lot <= 0)
		return 0;

	if (lot < 1)
		lot = 1;

	lot = floor(lot);
	return lot;
}

//------------------------------------------------------//
//  ORDER COUNT FOR THIS SCRIPT / ASSET
//------------------------------------------------------//

int CountAllOrdersForThisEA()
{
	return NumOpenLong + NumOpenShort + NumPendingLong + NumPendingShort;
}

//------------------------------------------------------//
//  EXISTING PENDING CHECKS
//------------------------------------------------------//

int NotExistingPendingBuyStop()
{
	if (NumPendingLong > 0)
		return 0;
	return 1;
}

int NotExistingPendingSellStop()
{
	if (NumPendingShort > 0)
		return 0;
	return 1;
}

//------------------------------------------------------//
//  TMF: MANAGE OPEN & PENDING TRADES
//------------------------------------------------------//

int SarTMF(var placementDate)
{
	var nowDate = wdate(0);
	var ageSec  = (nowDate - placementDate) * 24*60*60;

	// ---- Pending trades: expiry & staleness ----
	if (TradeIsPending) {
		// Could use ageSec, STALE_WINDOW_SEC, etc. if you
		// re-enable pending orders.
		return 0;
	}

	// ---- Open trades: delayed SL activation ----
	if (TradeIsOpen) {
		if (TradeStopLimit == 0.) {
			var curPrice = price();
			var lossPoints;

			if (TradeIsLong)
				lossPoints = (TradePriceOpen - curPrice) / PIP;
			else
				lossPoints = (curPrice - TradePriceOpen) / PIP;

			if (lossPoints >= DRAW_BEFORE_SL_POINTS) {
				if (TradeIsLong)
					TradeStopLimit = curPrice - EXTRA_SL_BUFFER_POINTS*PIP;
				else
					TradeStopLimit = curPrice + EXTRA_SL_BUFFER_POINTS*PIP;
			}
		}
	}

	return 0;
}

Last edited by TipmyPip; 2 hours ago.
Page 12 of 12 1 2 10 11 12

Moderated by  Petra 

Powered by UBB.threads™ PHP Forum Software 7.7.1