Gamestudio Links
Zorro Links
Newest Posts
ZorroGPT
by TipmyPip. 10/06/26 05:32
Purchase A8 full licence version
by jcl. 10/05/26 12:12
Respect History setting for Z systems
by AndrewAMD. 10/02/26 15:43
AUM Magazine
Latest Screens
Dorifto samurai
Shadow 2
Rocker`s Revenge
Stug 3 Stormartillery
Who's Online Now
0 registered members (), 14,965 guests, and 2 spiders.
Key: Admin, Global Mod, Mod
Newest Members
JimSimons, julienp, julienper, KelleyAbbey, Yopachi
19246 Registered Users
Active Threads | Active Posts | Unanswered Today | Since Yesterday | This Week
Starting with Zorro
Yesterday at 05:32
Enjoy, and Improve the Strategy.
259 98,192 Read More
Zorro and the Brokers
10/05/26 16:36
Contact support for this. They can be reached here:
support@opgroup.de
1 36 Read More
Starting with Gamestudio
10/05/26 12:12
You'll get a license key that unlocks the A8 demo version to a full version.
10 1,745 Read More
Starting with Zorro
10/05/26 12:02
I readily believe that you get gaps and bad results with your settings. Unless you trade on the Moscow stock exchange, better use the default weekend and time zone for currencies. Their weekend begins with market close in New York and ends at market open in Sydney. Even if your broker has weekend bars of currencies, they are not from regular trading, and better don't use them for a strategy.
1 128 Read More
Zorro Scripts
10/03/26 14:42
// ---- Real-trade scan buffers: rebuilt every bar, nothing carried ---- [R-33]
#define SCAN_NA 16 // [R-33] max assets in the list
#define SCAN_W 4 // [R-33] events kept per asset and bar
int ScanFillN[SCAN_NA], ScanClsN[SCAN_NA];
var ScanFillID[64], ScanFillDir[64], ScanFillPx[64]; // [R-33] 64 = SCAN_NA * SCAN_W
var ScanClsID[64], ScanClsPx[64];
int FltBars = 0, FltGreen = 0; // [R-22] filter census, trace only

// [R-33] Index of an asset in the list, -1 if absent.
int scanIdx(string Name)
{
int i;
for(i = 0; i < NumAssetsListed; i++)
if(strcmp(Name, Assets[i]) == 0) return i;
return -1;
}

// [R-33] Slot of this bar's fill on asset k in direction Dir, -1 if none.
int scanFill(int k, int Dir)
{
int j;
for(j = 0; j < ScanFillN[k]; j++)
if(j < SCAN_W && ScanFillDir[k*SCAN_W + j] == Dir) return j;
return -1;
}

// [R-33] Slot of this bar's close of trade ID on asset k, -1 if none.
int scanCls(int k, var ID)
{
int j;
for(j = 0; j < ScanClsN[k]; j++)
if(j < SCAN_W && ScanClsID[k*SCAN_W + j] == ID) return j;
return -1;
}

// [R-28] Classify a closed signal by its move before costs, signed by direction.
// [R-28] A move of exactly zero changes nothing.
void classify(vars PrevLoss, vars HaveHist, int Dir, int How, var Move)
{
printf("\n@SIG,%s,%i,%i,%i,%.8f", Asset, (int)Bar, Dir, How, (var)Move); // [R-28] trace
if(Move < 0) { PrevLoss[0] = 1; HaveHist[0] = 1; }
else if(Move > 0) { PrevLoss[0] = 0; HaveHist[0] = 1; }
}

function run()
{
// ---- Engine / mode setup ---------------------------------- [R-01..R-05]
BarPeriod = 1440; // [R-01] daily bars
BarOffset = 940; // [R-01] bar starts 15:40 in the bar time zone
set(LOGFILE); // [R-03] export logs and statistics files
set(TICKS); // [R-02] tick-precise intrabar simulation (D021)
Verbose = 3; // [R-03] skipped trades + parameter errors
// !! [R-03] Warning 047 verbosity is OBSERVED, not documented -- see 3.1.

// ---- Data source ------------------------------------------------ [R-04]
// !! [R-04] '*' reads the year files but keeps Zorro's silent bare-file
// !! fallback; the AssetFirstBar preflight below is the only control on it.
History = "put your \\Zorro\\History\\*.t6"; // [R-04]
NumYears = 20; // [R-05] simulation window
EndDate = 20261001; // [R-05] window end pinned (D029 Add. 3)

// ---- Parameter block -------------- [R-07, R-08, R-24, R-26, R-27, R-31]
int EntryDays = 20; // [R-07] System 1 entry channel, trading days
int ExitDays = 10; // [R-07] System 1 exit channel, trading days
int FailDays = 55; // [R-07] failsafe entry channel, trading days
int NPeriod = 20; // [R-26] N = average true range over 20 days
var StopMult = 2.0; // [R-27] hard stop at 2N from the fill price
int BreakTicks = 1; // [R-08] strict break: price increments beyond the level

// ---- Warm-up ---------------------------------------------- [R-09, R-26]
LookBack = 70; // [R-09] covers 55-day channel and 20-day N
UnstablePeriod = 40; // [R-26] recursive TA-Lib indicators re-run over 40 bars

// ---- Order handling ------------------------------------- [R-10..R-13]
EntryTime = 2; // [R-11] pending order lifetime, bars. INERT (see R-18)
Fill = 2; // [R-12] alternative order filling (D023)
Hedge = 0; // [R-13] netting by ASSET, not by algo

// ---- Universe --------------------------------------------------- [R-06]
if(is(INITRUN))
assetList("AssetsDryRunP7"); // [R-06] frozen P7 (D019)

MaxLong = 1; // [R-10] one position per side per asset
MaxShort = 1; // [R-10] magnitude live, sign inert (see R-18)

// ---- Real-trade scan: this bar's fills and closes ------------- [R-33]
// [R-33] Above the asset loop: enumeration loops cannot be nested.
int si, sk, ss;
for(si = 0; si < SCAN_NA; si++) { ScanFillN[si] = 0; ScanClsN[si] = 0; }
for(past_trades) {
if(TradeID != 0) {
sk = scanIdx(TradeAsset);
if(sk >= 0) {
// !! [R-33] TradeInt is 0 on a new trade: OBSERVED, not documented.
if(TradeInt[15] == 0) { // [R-33] fill not seen yet
TradeInt[15] = 1;
if(ScanFillN[sk] < SCAN_W) {
ss = sk*SCAN_W + ScanFillN[sk];
ScanFillID[ss] = TradeID; ScanFillDir[ss] = ifelse(TradeIsLong, 1, -1);
ScanFillPx[ss] = TradePriceOpen;
}
ScanFillN[sk] += 1;
}
if(TradeIsClosed && TradeInt[14] == 0) { // [R-33] close not seen yet
TradeInt[14] = 1;
if(ScanClsN[sk] < SCAN_W) {
ss = sk*SCAN_W + ScanClsN[sk];
ScanClsID[ss] = TradeID; ScanClsPx[ss] = TradePriceClose;
}
ScanClsN[sk] += 1;
}
}
}
}
if(is(EXITRUN))
printf("\n@FGR,%i,%i", FltGreen, FltBars); // [R-22] filter census, trace only

for(listed_assets)
{
// [R-25] for(listed_assets) only assigns Asset; it does not select.
if(!asset(Asset)) continue;

// [R-04] Reject any asset whose history does not cover the window.
if(AssetFirstBar > 0) {
printf("\n SKIP %s -- history starts at bar %i/%i",
Asset, (int)AssetFirstBar, (int)NumBars);
continue;
}

// [R-08] Read PIP inside the loop: it is an asset-specific parameter.
var BreakOffset = BreakTicks * PIP;

// ---- Price series ------------------------------------------------
vars H = series(priceHigh());
vars L = series(priceLow());

// ---- Rolling trading-day channels ------------------ [R-15, R-25]
// [R-25] Per-asset state lives in series(), NEVER in a bare static.
// [R-15] Carried as series so the code can read the level that was
// actually RESTING during a given bar -- see R-16.
vars ChEntryHigh = series(0), ChEntryLow = series(0);
vars ChExitLow = series(0), ChExitHigh = series(0);
vars ChFailHigh = series(0), ChFailLow = series(0);

ChEntryHigh[0] = MaxVal(H, EntryDays); // 20-day high
ChEntryLow[0] = MinVal(L, EntryDays); // 20-day low
ChExitLow[0] = MinVal(L, ExitDays); // 10-day low
ChExitHigh[0] = MaxVal(H, ExitDays); // 10-day high
ChFailHigh[0] = MaxVal(H, FailDays); // 55-day high
ChFailLow[0] = MinVal(L, FailDays); // 55-day low

// ---- Volatility primitive N -------------------------------- [R-26]
vars N = series(ATR(NPeriod));

// ---- Warm-up counter ---------------------------------------- [R-09]
vars BarsSeen = series(0);
BarsSeen[0] = BarsSeen[1] + 1;

// ---- Shadow-tracker series -------------------- [R-22, R-25, R-28]
// [R-25] Created ABOVE the warm-up gate: series() calls must never be
// skipped by a bar-varying condition. Only their [0] elements are set
// conditionally, further down.
vars ShDir = series(0); // shadow signal: 0 none, +1 long, -1 short
vars ShEntry = series(0); // shadow entry price (level + break offset)
vars ShAdv = series(0); // [R-28] the 2N adverse level, fixed at signal
vars PrevLoss = series(0); // 1 = last CLOSED shadow signal was a loser
vars HaveHist = series(0); // 1 = at least one shadow signal has closed

ShDir[0] = ShDir[1];
ShEntry[0] = ShEntry[1];
ShAdv[0] = ShAdv[1];
PrevLoss[0] = PrevLoss[1];
HaveHist[0] = HaveHist[1];

// ---- Real-trade link series ---------------------------- [R-33, R-25]
vars TrkID = series(0); // [R-33] real trade tied to the open signal, 0 none
vars PlL = series(0); // [R-33] 1 = a 20-day long entry rested this bar
vars PlS = series(0); // [R-33] 1 = a 20-day short entry rested this bar
TrkID[0] = TrkID[1];

// [R-09] Warm-up gate. Every series() call for this asset is ABOVE it.
if(BarsSeen[0] < 70) continue;

// ---- Level-or-distance preflight -------------------- [R-17, R-32]
var HalfPrice = 0.5 * priceClose();
bool badEntryHigh = (ChEntryHigh[0] < HalfPrice);
bool badEntryLow = (ChEntryLow[0] < HalfPrice);
bool badExitLow = (ChExitLow[0] < HalfPrice);
bool badExitHigh = (ChExitHigh[0] < HalfPrice);
bool badFailHigh = (ChFailHigh[0] < HalfPrice);
bool badFailLow = (ChFailLow[0] < HalfPrice);
bool badStopDist = (StopMult * N[0] >= HalfPrice);

if(badEntryHigh || badEntryLow || badExitLow || badExitHigh || badFailHigh || badFailLow)
printf("\n!!! %s bar %i: channel level below half the asset price %.5f (EntryHigh %.5f, EntryLow %.5f, ExitLow %.5f, ExitHigh %.5f, FailHigh %.5f, FailLow %.5f) -- Zorro reads such a value as a DISTANCE, not a level (stop.htm).",
Asset, (int)Bar, (var)HalfPrice, (var)ChEntryHigh[0], (var)ChEntryLow[0],
(var)ChExitLow[0], (var)ChExitHigh[0], (var)ChFailHigh[0], (var)ChFailLow[0]);
if(badStopDist)
printf("\n!!! %s bar %i: 2N stop distance %.5f is at or above half the asset price %.5f -- Zorro would read it as a LEVEL, not a distance (stop.htm).",
Asset, (int)Bar, (var)(StopMult * N[0]), (var)HalfPrice);
// [R-32] Exit levels are NOT gated -- suppressing an exit removes protection.
if(badExitLow || badExitHigh)
printf("\n@XLV,%s,%i,%.8f,%.8f,%.8f", Asset, (int)Bar,
(var)ChExitLow[0], (var)ChExitHigh[0], (var)HalfPrice);

// ---- One-bar order-placement lag -------------------------- [R-16]
// [R-16] Convention: every TEST reads [1], every ORDER is placed with [0].
var RestEntryHigh = ChEntryHigh[1];
var RestEntryLow = ChEntryLow[1];
var RestExitLow = ChExitLow[1];
var RestExitHigh = ChExitHigh[1];
var RestFailHigh = ChFailHigh[1];
var RestFailLow = ChFailLow[1];
var RestN = N[1];

// [R-08] Entry breaks are STRICT: the offset is in the test and in the
// order, so shadow and real fill on the same bar at the same price.
bool hitEntryHigh = (H[0] >= RestEntryHigh + BreakOffset);
bool hitEntryLow = (L[0] <= RestEntryLow - BreakOffset);
// [R-20] Exit stops are taken AT the level -- the break rule is on entries.
bool hitExitLow = (L[0] <= RestExitLow);
bool hitExitHigh = (H[0] >= RestExitHigh);

// ---- Shadow signal bookkeeping ---------- [R-22, R-28, R-21, R-33]
int ScanK = scanIdx(Asset); // [R-33]
int RealClosed = 0, Slot = -1, FillSlot = -1, OpenDir = 0;
var RealExit = 0, Rested20 = 0;
if(TrkID[0] != 0) {
Slot = scanCls(ScanK, TrkID[0]);
if(Slot >= 0) { RealClosed = 1; RealExit = ScanClsPx[ScanK*SCAN_W + Slot]; }
}
int ShStart = ShDir[0]; // [R-22] shadow state at bar start
if(ShStart != 0 && TrkID[0] != 0)
{
// [R-33] A taken breakout closes with its real trade, never on the shadow tests.
if(RealClosed) {
classify(PrevLoss, HaveHist, ShStart, 3, (RealExit - ShEntry[0]) * ShStart);
ShDir[0] = 0;
}
}
else if(ShStart > 0)
{
// [R-28] 2N adverse excursion tested BEFORE the 10-day exit.
if(L[0] <= ShAdv[0]) {
classify(PrevLoss, HaveHist, 1, 1, ShAdv[0] - ShEntry[0]);
ShDir[0] = 0;
} else if(hitExitLow) {
classify(PrevLoss, HaveHist, 1, 2, RestExitLow - ShEntry[0]);
ShDir[0] = 0;
}
}
else if(ShStart < 0)
{
if(H[0] >= ShAdv[0]) {
classify(PrevLoss, HaveHist, -1, 1, ShEntry[0] - ShAdv[0]);
ShDir[0] = 0;
} else if(hitExitHigh) {
classify(PrevLoss, HaveHist, -1, 2, ShEntry[0] - RestExitHigh);
ShDir[0] = 0;
}
}
if(RealClosed) TrkID[0] = 0;
if(ShStart == 0)
{
// [R-21] Outside-bar tie-break: long tested first, deterministically.
if(hitEntryHigh) OpenDir = 1;
else if(hitEntryLow) OpenDir = -1;
// [R-22] No same-bar close: a shadow opened here is tested from
// the NEXT bar.
}
else if(ShDir[0] == 0) // [R-22] closed on this bar
{
// [R-22] An OPPOSITE break on the closing bar opens a new signal.
if(ShStart > 0 && hitEntryLow) OpenDir = -1;
else if(ShStart < 0 && hitEntryHigh) OpenDir = 1;
}
if(OpenDir != 0)
{
ShDir[0] = OpenDir;
if(OpenDir > 0) ShEntry[0] = RestEntryHigh + BreakOffset;
else ShEntry[0] = RestEntryLow - BreakOffset;
ShAdv[0] = ShEntry[0] - OpenDir * StopMult * RestN; // [R-28]
// [R-33] Taken: a same-direction fill this bar, from a 20-day order rested last bar.
FillSlot = scanFill(ScanK, OpenDir);
Rested20 = PlS[1];
if(OpenDir > 0) Rested20 = PlL[1];
if(FillSlot >= 0 && Rested20 == 1) {
TrkID[0] = ScanFillID[ScanK*SCAN_W + FillSlot];
ShEntry[0] = ScanFillPx[ScanK*SCAN_W + FillSlot]; // [R-33] the real fill
Slot = scanCls(ScanK, TrkID[0]);
if(Slot >= 0) {
// [R-33] The real trade also closed on its fill bar.
classify(PrevLoss, HaveHist, OpenDir, 3, (ScanClsPx[ScanK*SCAN_W + Slot] - ShEntry[0]) * OpenDir);
ShDir[0] = 0;
TrkID[0] = 0;
}
}
}

// ---- Previous-signal filter ------------------------ [R-22, R-23]
// [R-22] Read AFTER this bar's shadow update.
// [R-23] First signal on each asset is taken: there is no previous one.
bool filterOK = (HaveHist[0] == 0) || (PrevLoss[0] > 0);
FltBars += 1; if(filterOK) FltGreen += 1; // [R-22] census, trace only

// ---- Real orders ---- [R-14, R-18..R-21, R-27, R-29..R-32]
if(NumOpenLong > 0)
{
// [R-19] Cancel the opposite pending order left alive by the fill.
exitShort(0);
// [R-20, R-30] Ratcheted 10-day channel exit, re-issued each bar at
// the current level; it can only tighten. [R-27] the 2N stop stays
// attached and the nearer of the two closes the trade.
exitLong(0, ChExitLow[0]);
}
else if(NumOpenShort > 0)
{
exitLong(0);
exitShort(0, ChExitHigh[0]);
}
else
{
// [R-18] Cancel yesterday's unfilled orders, then re-place fresh.
// Reached ONLY when flat -- the branch structure IS the guard.
exitLong(0);
exitShort(0);

Stop = StopMult * N[0]; // [R-27] 2N hard stop, a DISTANCE to the fill price

// [R-29] Filter green: the 20-day levels. Filter red: the 55-day failsafe.
var LongLevel = ChEntryHigh[0];
var ShortLevel = ChEntryLow[0];
bool badLong = badEntryHigh;
bool badShort = badEntryLow;
if(!filterOK) {
LongLevel = ChFailHigh[0]; badLong = badFailHigh;
ShortLevel = ChFailLow[0]; badShort = badFailLow;
}

// [R-14] Family B: resting stop orders AT the level, not close tests.
// [R-08] Entry carries the break offset.
// [R-32] An order the engine would misread is suppressed, per side.
if(badLong || badStopDist)
printf("\n@SUP,%s,%i,L,%.8f,%.8f,%.8f", Asset, (int)Bar,
(var)LongLevel, (var)HalfPrice, (var)(StopMult * N[0]));
else {
enterLong(1, LongLevel + BreakOffset);
PlL[0] = filterOK; // [R-33] 1 = rested at the 20-day level
}

if(badShort || badStopDist)
printf("\n@SUP,%s,%i,S,%.8f,%.8f,%.8f", Asset, (int)Bar,
(var)ShortLevel, (var)HalfPrice, (var)(StopMult * N[0]));
else {
enterShort(1, ShortLevel - BreakOffset);
PlS[0] = filterOK; // [R-33] 1 = rested at the 20-day level
}
}
}
}
6 2,291 Read More
RangerZ & Z Systems
10/02/26 15:43
It works for me.

Two questions:
1. You did set the HistoryFolder value, correct?
2. You still have your asset and account lists in the original History folder, correct?

Documented here:
https://zorro-project.com/manual/en/ini.htm
1 108 Read More
Bug Hunt
09/30/26 18:35
If you use the default TradeTest.c script as-is with Interactive Brokers, it will not work. Here's why.

This line of code is the culprit:
Code
if(is(INITRUN)) brokerCommand(SET_ORDERTEXT,"TradeTest");


This of course looks like it would add a mere comment to a placed order. But that's not what happens with IB in particular.

Instead, it sets the IB order's OrderType string value, which is a critical field. So if the order type is set to "TradeTest", the test order won't work.

I expect that most newcomers to Zorro would not be able to figure this out without running the script in verbose mode and then debugging the script.

Before I remove the line:
Code
!Open IB Socket 4.03 at UTC 09-30 17:39
 ESZ6
 ESZ6

Trade: TradeTest ESZ6 2026-09-30
Assets AssetsFutures
 ESZ6
Buy Long ESZ6
!Order 4137 ES-FUT-ESZ6-ES-CME BUY TradeTest DAY 2 ES-FUT--0.00--CME/-ES-USD
!Error validating request.-'v' : cause - Invalid order type was entered ES-FUT--0.00--CME/-ES-USD
!Order rejected: error validating request.-'v' : cause - invalid order type was entered
Warning 075 (ESZ6::L) - can't open 2@7762 at 17:39:24

After I remove the line:
Code
!Open IB Socket 4.03 at UTC 09-30 17:39
 ESZ6
 ESZ6

Trade: TradeTest ESZ6 2026-09-30
Assets AssetsFutures
 ESZ6
Buy Long ESZ6
!Order 4147 ES-FUT-ESZ6-ES-CME BUY MKT DAY 2 ES-FUT--0.00--CME/-ES-USD
[ESZ6::L04147] Long 2@7763.50  at 17:42:45
4147: Lots 2 Target 2 Open 7763.50000 Close 7763.50000
4147: Lots 2 Target 2 Open 7763.50000 Close 7763.75000


Note that "TradeTest" gets replaced with "MKT" (market order).
0 29 Read More

Gamestudio download | Zorro platform | shop | Data Protection Policy

oP group Germany GmbH | Birkenstr. 25-27 | 63549 Ronneburg / Germany | info (at) opgroup.de

Powered by UBB.threads™ PHP Forum Software 7.7.1