Hello,
You are mixing two things:
a) equity derived metrics (such as drawdown) - that
represent ARRAYS and that are available already
b) other metrics (like trade profits, trade
duration) that are single SCALARS
a)
Any EQUITY-based indicator is already possible via
Equity chart.
Sample Equity chart contains:
equity
cash,
drawdown (underwater equity)
bars since last equity high.
If you want to customize equity chart simply modify
_Portfolio Equity.afl file.
Fred has done so and he is using for example
Log(Equity) in his IO together with some other metrics
derived from Equity. It does not require any COM.
Just take portfolio equity usign Foreign("~~~EQUITY", "C")
Below is the code that Fred is using in his IO for
the reference.
Everybody can modify his/her Portfolio Equity formula to suit one's
need.
The code is open and you are free to modify it.
b)
As to
> That SYSTEM PERFORMANCE INDICATORS are not offered as standard (build
in) indicators is simply a lack of imagination.
> To plot the UPI, number of winning trades, trade profits, trade
duration, or other system performance statistic
> on a time scale simply makes a lot common sense. btw,
> Applying these functions to price arrays can also give very
interesting results. Price and equity arrays are not that different.
These metrics are NUMBERS. Just single SCALARS.
They do NOT change over time. They are constant for single
backtest.
If you plot them you will get FLAT
LINE.
> Saying "If you really have to plot them" is like saying "if you really
have to make money".
> The lack of System Performance Indicators is simply a void in
technical analysis ready (LONG OVERDUE!) to
> be filled. To have to use the CBT, export the data, import the data,
etc. to create
> System Performance Indicators is simply too much work; no one will do
it.
The system performance metrics are single NUMBERS (scalars). Just like 23.4.
This is a number that does not change. When plotted - it is FLAT LINE.
They are not "overdue" because they simply are reported in BACKTEST REPORT,
as numbers.
The same as in Tradestation, Wealth Lab, Trading Recipes, or
whatever.
> Most of us are here to trade and not to > learn new programming
languages;
> OLE and CBT are advanced tools for programmers. imo, System Performance
Indicators should be as readily available as the RSI() and
CMO().
Again, you are missing the point. Backtest metrics
are scalars, not arrays like RSI/CMO.
The metrics are available as single numbers AFTER
backtest.
If some metric is say 23.4 plotting it would result
in flat line like
Plot( 23.4, "Sample metric plot", colorRed );
Best
regards,
Tomasz Janeczko
amibroker.com
/**** BELOW CODE IS A PART OF IO.zip (Intelligent Optimizer by Fred
Tonetti) archive from the AmiBroker Mailing List File section ***/
/*** It shows example customization of built-in portfolio equity chart
*/
#pragma nocache
MaxGraph = 10;
GraphZOrder
= 1;
GraphYSpace = 5;
Arrows = ParamToggle("Arrows",
"No|Yes", 1);
BIR =
IIf(Status("BarInRange") > 0, 1, 0);
ISeq = Foreign("~~~EQUITY",
"C", 1);
CurEq = Foreign("~~IO~Equity",
"C", 1);
CurIOS = Foreign("~~IO~Equity", "V",
1);
CurSig = Foreign("~~IO~Equity", "I", 1);
CS128 = IIf(CurSig >= 128, 1,
0);
CurSig = IIf(CS128 == 1, CurSig - 128,
CurSig);
CS64 = IIf(CurSig >= 64, 1,
0);
CurSig = IIf(CS64 == 1, CurSig - 64,
CurSig);
CS32 = IIf(CurSig >= 32, 1,
0);
CurSig = IIf(CS32 == 1, CurSig - 32,
CurSig);
CS16 = IIf(CurSig >= 16, 1,
0);
CurSig = IIf(CS16 == 1, CurSig - 16,
CurSig);
CS8 = IIf(CurSig >= 8, 1,
0);
CurSig = IIf(CS8 == 1, CurSig - 8,
CurSig);
CS4 = IIf(CurSig >= 4, 1,
0);
CurSig = IIf(CS4 == 1, CurSig - 4,
CurSig);
CS2 = IIf(CurSig >= 2, 1,
0);
CurSig = IIf(CS2 == 1, CurSig - 2,
CurSig);
CS1 = IIf(CurSig >= 1, 1,
0);
CurSig = IIf(CS1 == 1, CurSig - 1,
CurSig);
BarEnt = IIf(CS1 == 1 OR CS4 == 1 OR
CS16 == 1 OR CS64 == 1, 1, 0);
CurEnt = IIf(BarEnt != 0, CurEq,
0);
LastIS = CurIOS == 0 AND Ref(CurIOS, 1)
!= 0;
OtherOOS = CurIOS != Ref(CurIOS, 1);
MaxEq =
Highest(CurEq);
FlatEq = IIf(BIR, BarsSince(MaxEq >
Ref(MaxEq,-1)),0);
MaxFlat = Highest(FlatEq);
LMaxFlat =
LastValue(MaxFlat) * (1 + GraphYSpace / 100);
LogEq =
log10(CurEq);
CurDD = IIf(CurEq < MaxEq, 100
* (MaxEq - CurEq) / MaxEq, 0);
RCurDD = round(CurDD * 100) /
100;
MaxDD = Highest(CurDD);
RMaxDD =
round(MaxDD * 100) / 100;
LMaxDD = LastValue(MaxDD) * (1 +
GraphYSpace / 100);
SqrDD = CurDD ^
2;
CumDD = Cum(SqrDD);
MaxEnt =
Highest(CurEnt);
CurDDE = IIf(CurEq < MaxEnt, 100 * (MaxEnt -
CurEq) / MaxEnt, 0);
RCurDDE = round(CurDDE * 100) /
100;
MaxDDE = Highest(CurDDE);
RMaxDDE = round(MaxDDE *
100) / 100;
FirstBar =
LastValue(ValueWhen(Status("FirstBarInRange") > 0, Cum(1)));
LastBar
= LastValue(ValueWhen(Status("LastBarInRange") > 0,
Cum(1)));
TotBars = LastValue(Cum(1));
BarNo =
ValueWhen(BIR > 0, Cum(1) - FirstBar + 1);
NoBars =
LastValue(BarNo);
Dates =
DateNum();
Days = ValueWhen(BIR > 0, IIf(Dates !=
Ref(Dates,-1), 1, 0));
TotDays =
Cum(Days);
BPD = round(BarNo /
TotDays);
BAHEq =
ValueWhen(BIR > 0, Ref(CurEq, -(BarNo - 1)) * (C / Ref(C, -(BarNo -
1))));
BAHMaxEq = Highest(BAHEq);
BAHFlatEq
= IIf(BIR, BarsSince(BAHMaxEq > Ref(BAHMaxEq,-1)),0);
BAHMaxFlat =
Highest(BAHFlatEq);
BAHLMaxFlat = LastValue(BAHMaxFlat) * (1 + GraphYSpace /
100);
BAHCurDD = IIf(BAHEq <
BAHMaxEq, 100 * (BAHMaxEq - BAHEq) / BAHMaxEq, 0);
BAHRCurDD =
round(BAHCurDD * 100) / 100;
BAHMaxDD =
Highest(BAHCurDD);
BAHRMaxDD = round(BAHMaxDD * 100) /
100;
BAHLMaxDD = LastValue(BAHMaxDD) * (1 + GraphYSpace /
100);
BAHSqrDD = BAHCurDD ^
2;
BAHCumDD = Cum(BAHSqrDD);
LogBAHEq = log10(BAHEq);
CAR = ValueWhen(BIR
> 0, 100 * ((CurEq / Ref(CurEq, -(BarNo - 1))) ^ (1 / (BarNo / BPD / 252))
-1));
Ann = ValueWhen(BIR > 0, 100 * ((CurEq
/ Ref(CurEq, -(252 * BPD)) - 1)));
MAR =
ValueWhen(BIR > 0, CAR / MaxDD);
UI =
ValueWhen(BIR > 0, sqrt(CumDD / BarNo));
UPI
= (CAR - 5.4) / UI;
BAHCAR = ValueWhen(BIR > 0, 100 *
((BAHEq / Ref(BAHEq, -(BarNo - 1))) ^ (1 / (BarNo / BPD / 252))
-1));
BAHAnn = ValueWhen(BIR > 0, 100 * ((BAHEq / Ref(BAHEq,
-(252 * BPD)) - 1)));
BAHMAR = ValueWhen(BIR > 0, BAHCAR /
BAHMaxDD);
BAHUI = ValueWhen(BIR > 0, sqrt(BAHCumDD /
BarNo));
BAHUPI = (BAHCAR - 5.4) / BAHUI;
OSCAR1 = ValueWhen(CurIOS >= 1, 100
* ISEq / Highest(ValueWhen(LastIS == 1, ISEq)));
OSMaxEq1 = ValueWhen(CurIOS
>= 1, Highest(ISEq));
OSCurDD1 = IIf(CurIOS >= 1, 100 * (OSMaxEq1 -
ISEq) / OSMaxEq1, 0);
OSMaxDD1 = Highest(OSCurDD1);
OSMAR1 =
OSCAR1 / OSMaxDD1;
OSCAR2 = ValueWhen(CurIOS >= 1, 100
* CurEq / Highest(ValueWhen(LastIS == 1, CurEq)));
OSMaxEq2 =
ValueWhen(CurIOS >= 1, Highest(CurEq));
OSCurDD2 = IIf(CurIOS >= 1, 100
* (OSMaxEq2 - CurEq) / OSMaxEq2, 0);
OSMaxDD2 =
Highest(OSCurDD2);
OSMAR2 = OSCAR2 / OSMaxDD2;
WFEcar = 100 * OSCAR2 /
OSCAR1;
WFEmar = 100 * OSMAR2 / OSMAR1;
b0 =
LastValue(LinRegIntercept(Ref(LogEq, -(TotBars - LastBar)),
NoBars));
m =
LastValue(LinRegSlope(Ref(LogEq, -(TotBars - LastBar)),
NoBars));
y = m * BarNo +
b0;
BarsCum = ValueWhen(BIR > 0,
Cum(BarNo));
AvgBar = LastValue(BarsCum) /
NoBars;
SRDevSQ = ValueWhen(BIR > 0, sqrt(Cum((BarNo - AvgBar) ^
2)));
ErrEq = LastValue(StdErr(Ref(logEq, -(TotBars -
LastBar)), NoBars));
KRatio = ValueWhen(BIR > 0, m * SRDevSQ /
ErrEq / sqrt(NoBars));
Title1 = EncodeColor(ColorRGB(160,160,160)) +
"LinReg= " + EncodeColor(ColorRGB(128,128,255)) + WriteVal(10 ^
y, 3.0) + " "
+
EncodeColor(ColorRGB(160,160,160)) + "CurFlat=" +
EncodeColor(ColorRGB(255,223, 0)) +
WriteVal(FlatEq, 3.0) + " "
+
EncodeColor(ColorRGB(160,160,160)) + "Ann=" +
EncodeColor(ColorRGB( 0,255, 0)) +
WriteVal(Ann, 3.2) + "% "
+
EncodeColor(ColorRGB(160,160,160)) + "MDDE=" +
EncodeColor(ColorRGB(255,128, 0)) +
WriteVal(MaxDDE, 3.2) + "% "
+
EncodeColor(ColorRGB(160,160,160)) + "CDD=" +
EncodeColor(ColorRGB(255, 0, 0)) +
WriteVal(CurDD, 3.2) + "% "
+
EncodeColor(ColorRGB(160,160,160)) + "wfeCAR=" +
EncodeColor(ColorRGB(255,255, 0)) +
WriteVal(WFECar, 3.2) + "% "
+
EncodeColor(ColorRGB(160,160,160)) + "wfeMAR=" +
EncodeColor(ColorRGB(255,255, 0)) +
WriteVal(WFEMAR, 3.2) + "% ";
Title2 = "\n"
+
EncodeColor(ColorRGB(160,160,160)) + "Equity = " +
EncodeColor(ColorRGB(224,224,224)) +
WriteVal(CurEq, 3.0) + " "
+
EncodeColor(ColorRGB(160,160,160)) + "MaxFlat=" +
EncodeColor(ColorRGB(255,223, 0)) + WriteVal(MaxFlat,
3.0) + " " +
EncodeColor(ColorRGB(160,160,160)) + "CAR=" +
EncodeColor(ColorRGB( 0,255, 0)) +
WriteVal(CAR, 3.2) + "% "
+
EncodeColor(ColorRGB(160,160,160)) + "MDD=" +
EncodeColor(ColorRGB(255, 0, 0)) +
WriteVal(MaxDD, 3.2) + "% "
+
EncodeColor(ColorRGB(160,160,160)) + "MAR=" +
EncodeColor(ColorRGB( 0,255, 0)) +
WriteVal(MAR, 3.2) + " "
+
EncodeColor(ColorRGB(160,160,160)) + "UI=" +
EncodeColor(ColorRGB(255, 0,255)) +
WriteVal(UI, 3.2) + " "
+
EncodeColor(ColorRGB(160,160,160)) + "UPI=" +
EncodeColor(ColorRGB( 0,255, 0)) +
WriteVal(UPI, 3.2) + " "
+
EncodeColor(ColorRGB(160,160,160)) + "KR=" +
EncodeColor(ColorRGB(160,255,160)) + WriteVal(KRatio,
3.2) + " ";
Title3 = "\n"
+
EncodeColor(ColorRGB(160,160,160)) + "B & H = " +
EncodeColor(ColorRGB(128,128,128)) +
WriteVal(BAHEq, 3.0) + " "
+
EncodeColor(ColorRGB(160,160,160)) + "MaxFlat=" +
EncodeColor(ColorRGB(208,176, 0)) + WriteVal(BAHMaxFlat, 3.0) + " "
+
EncodeColor(ColorRGB(160,160,160)) + "CAR=" +
EncodeColor(ColorRGB( 0,192, 0)) +
WriteVal(BAHCAR, 3.2) + "% "
+
EncodeColor(ColorRGB(160,160,160)) + "MDD=" +
EncodeColor(ColorRGB(208, 0, 0)) + WriteVal(BAHMaxDD,
3.2) + "% " +
EncodeColor(ColorRGB(160,160,160)) + "MAR=" +
EncodeColor(ColorRGB( 0,192, 0)) +
WriteVal(BAHMAR, 3.2) + " "
+
EncodeColor(ColorRGB(160,160,160)) + "UI=" +
EncodeColor(ColorRGB(208, 0,208)) +
WriteVal(BAHUI, 3.2) + " "
+
EncodeColor(ColorRGB(160,160,160)) + "UPI=" +
EncodeColor(ColorRGB( 0,192, 0)) +
WriteVal(BAHUPI, 3.2);
Title = Title1 + Title2 + Title3;
Plot(IIf(BarNo > 0 AND BIR > 0,
-RCurDD, -1e10), "CDD", colorDarkRed, styleThick |
styleOwnScale | styleArea, -LMaxDD, LMaxDD);
Plot(IIf(BarNo >
0 AND BIR == 0, -RCurDD, -1e10), "CDD", colorDarkRed,
styleThick | styleOwnScale | styleLine, -LMaxDD,
LMaxDD);
Plot(IIf(BarNo >
0,
-RMaxDD, -1e10), "MDD", colorDarkRed, styleThick |
styleOwnScale,
-LMaxDD, LMaxDD);
Plot(IIf(BarNo > 0 AND BIR > 0,
-RCurDDE, -1e10), "CDDE", colorOrange, styleThick | styleOwnScale |
styleArea, -LMaxDD, LMaxDD);
Plot(IIf(BarNo > 0 AND BIR == 0,
-RCurDDE, -1e10), "CDDE", colorOrange, styleThick | styleOwnScale |
styleLine, -LMaxDD, LMaxDD);
Plot(IIf(BarNo >
0,
-RMaxDDE, -1e10), "MDDE", colorOrange, styleThick |
styleOwnScale,
-LMaxDD, LMaxDD);
Plot(IIf(BarNo >
0,
FlatEq, -1e10), "CF", colorGold,
styleThick | styleOwnScale | styleArea, -LMaxFlat, LMaxFlat);
Plot(IIf(BarNo
>
0,
MaxFlat, -1e10), "MF", colorGold, styleThick
|
styleOwnScale,
-LMaxFlat, LMaxFlat);
Plot(LastIS, "LastIS",
colorLightGrey, styleHistogram | styleThick | styleNoLabel |
styleOwnScale);
Plot(OtherOOS, "OtherOOS", colorLightGrey, styleHistogram
|
styleNoLabel | styleOwnScale);
Plot(IIf(BIR > 0,
Y, -1e10), "L/R Eq",
colorBlue, styleThick |
styleNoLabel);
Plot(IIf(BIR > 0, LogBAHEq, -1e10), "BAH Eq",
colorGrey50, styleThick | styleNoLabel);
Plot(IIf(BIR >
0, LogEq, -1e10), "Sys Eq", colorLightGrey, styleThick |
styleNoLabel);
S1 = (CS1 == 1) *
shapeUpArrow;
S2 = (CS2 == 1) *
shapeDownArrow;
S4 = (CS4 == 1) *
shapeDownArrow;
S8 = (CS8 == 1) *
shapeUpArrow;
S16 = (CS16 == 1) * shapeUpArrow;
S32 =
(CS32 == 1) * shapeDownArrow;
S64 = (CS64 == 1) *
shapeDownArrow;
S128 = (CS128 == 1) * shapeUpArrow;
if (Arrows == True)
{
PlotShapes(IIf(BIR > 0, S2, -1e10),
colorWhite, 0, LogEq,
-11);
PlotShapes(IIf(BIR > 0, S8, -1e10),
colorWhite, 0, LogEq, -11);
PlotShapes(IIf(BIR > 0,
S1, -1e10), colorBrightGreen, 0, logEq, IIf(CS8, -17,
-11));
PlotShapes(IIf(BIR > 0, S4, -1e10),
colorRed, 0, logEq,
IIf(CS2, -17, -11));
PlotShapes(IIf(BIR > 0,
S32, -1e10), colorGrey50, 0, LogEq,
-11);
PlotShapes(IIf(BIR > 0, S128, -1e10),
colorGrey50, 0, LogEq, -11);
PlotShapes(IIf(BIR > 0,
S16, -1e10), colorBlue, 0,
LogEq, IIf(CS128, -17, -11));
PlotShapes(IIf(BIR > 0,
S64, -1e10),
11,
0, LogEq, IIf(CS32, -17, -11));
}