|
|
SGT_FW
by Aku_Aku. 05/31/26 11:05
|
|
|
|
|
|
|
XTB
by pr0logic. 05/18/26 12:27
|
|
|
|
|
|
|
0 registered members (),
6,352
guests, and 4
spiders. |
|
Key:
Admin,
Global Mod,
Mod
|
|
|
|
06/04/26 05:44
It can affect backtesting when MMI is used in a trade condition, filter, optimizer, or ML feature, because the changed MMI value can change whether a signal is true or false.
The original MMI code calculates a median over TimePeriod and then counts rising/falling behavior around that median. Zorro’s indicator source shows the old version using TimePeriod = Min(TimePeriod,g->nBar-1); and Median(Data,TimePeriod). The Median function sorts the data and returns the middle value within the given period.
When the backtest can change 1. When TimePeriod is even
Old:
var m = Median(Data,TimePeriod);
New:
var m = Median(Data,TimePeriod|1);
If TimePeriod = 100, then:
TimePeriod|1 = 101
So the median is calculated from 101 values instead of 100.
That can shift the median slightly. Since MMI compares every value against the median:
if(Data[i] > m && Data[i] > Data[i-1]) nl++; else if(Data[i] < m && Data[i] < Data[i-1]) nh++;
a small median shift can change nl or nh, which changes the returned MMI value.
This matters if your strategy does something like:
if(MMI(Price,100) > 75) enterLong();
A value changing from 74.9 to 75.2 can create a trade in one version but not the other.
2. Near the beginning of the backtest or WFO cycle
Old:
TimePeriod = Min(TimePeriod,g->nBar-1);
New:
TimePeriod = Min(TimePeriod,g->nBar-2);
The new version uses one less available bar when history is short.
This can affect the first valid bars after LookBack, or the beginning of a walk-forward cycle, especially if TimePeriod is close to the available history length.
Zorro uses LookBack to execute bars before trading begins so indicators have enough history. The manual says the first bar where trades can be entered is greater than or equal to LookBack, and LookBack should cover the longest period of all used indicators, assets, and time frames.
So this change can affect backtesting mostly when:
LookBack ? MMI period
or when TimePeriod is optimized and sometimes becomes large.
3. When MMI is used as a filter
Example:
vars Price = series(priceClose()); var MeanState = MMI(Price,100);
if(MeanState > 75) enterLong();
If the old version gives:
MMI_old = 74.8
and the new version gives:
MMI_new = 75.3
then the trade only happens with the new version.
That can change:
entry timing, number of trades, profit factor, drawdown, optimized parameters, WFO results
The Zorro manual notes that indicators often become buy/sell signals when they reach thresholds, cross each other, or cross the price curve.
4. When MMI period is optimized
This is a big one.
Example:
int MMIPeriod = optimize(100,50,300,10); var M = MMI(Price,MMIPeriod);
If some optimized values are even, the new version internally turns the median length odd:
100 -> 101 120 -> 121 200 -> 201
So the optimizer may find a different best parameter than before.
Zorro’s documentation specifically warns that when optimizing an indicator time period, LookBack should be set to at least the maximum period, otherwise the backtest period can change with the optimized value and affect results unexpectedly.
5
155
Read More
|
|
06/04/26 05:38
How to test whether your backtest is affected You can copy both versions into your script and compare them bar by bar. // Old MMI version
var MMI_old(vars Data,int TimePeriod)
{
TimePeriod = Min(TimePeriod,1000);
checkLookBack(TimePeriod);
TimePeriod = Min(TimePeriod,g->nBar-1);
if(TimePeriod < 2)
return 75;
var m = Median(Data,TimePeriod);
int i, nh = 0, nl = 0;
for(i = 1; i < TimePeriod; i++)
{
if(Data[i] > m && Data[i] > Data[i-1])
nl++;
else if(Data[i] < m && Data[i] < Data[i-1])
nh++;
}
return 100.*(nl+nh)/(TimePeriod-1);
}
// New MMI version
var MMI_new(vars Data,int TimePeriod)
{
TimePeriod = Min(TimePeriod,1000);
checkLookBack(TimePeriod);
TimePeriod = Min(TimePeriod,g->nBar-2);
if(TimePeriod < 2)
return 75;
var m = Median(Data,TimePeriod|1);
int i, nh = 0, nl = 0;
for(i = 1; i < TimePeriod; i++)
{
if(Data[i] > m && Data[i] > Data[i-1])
nl++;
else if(Data[i] < m && Data[i] < Data[i-1])
nh++;
}
return 100.*(nl+nh)/(TimePeriod-1);
}
function run()
{
BarPeriod = 60;
LookBack = 300;
asset("EUR/USD");
vars Price = series(priceClose());
int Period = 100;
var OldMMI = MMI_old(Price,Period);
var NewMMI = MMI_new(Price,Period);
plot("Old MMI",OldMMI,NEW,BLUE);
plot("New MMI",NewMMI,0,RED);
plot("Difference",NewMMI-OldMMI,NEW,GREEN);
static int ValueDiffs = 0;
static int SignalDiffs = 0;
if(!is(LOOKBACK))
{
if(abs(NewMMI-OldMMI) > 0.0001)
ValueDiffs++;
int OldSignal = OldMMI > 75;
int NewSignal = NewMMI > 75;
if(OldSignal != NewSignal)
{
SignalDiffs++;
printf("\nBar %i: Old MMI %.2f, New MMI %.2f",Bar,OldMMI,NewMMI);
}
}
if(is(EXITRUN))
{
printf("\nMMI value differences: %i",ValueDiffs);
printf("\nMMI signal differences: %i",SignalDiffs);
}
}What to look for If the green Difference plot is often zero, your backtest is probably not affected. If you see many lines like: Old MMI 74.95, New MMI 75.12 and your system uses a threshold near 75, then your backtest can change. The highest-risk cases are: if(MMI(Price,Period) > 75)
if(MMI(Price,Period) < 50)
if(crossOver(MMI_Series,Threshold)) The lowest-risk case is when MMI is only plotted and not used for trading decisions.
5
155
Read More
|
|
|