27 August 2011

e-ratio

e-ratio: How to measure your trading edge in 4 easy steps

e-ratio is a metrics that measures the edge of a trading system component. For example, we could use it to quantify the edge gained from a donchian channel breakout entry signal.
The concept

The e-ratio quantifies the edge by calculating the overall amount trades go in your favor versus the overall amount trades go against you. The higher value the value of the e-ratio, the more trades move in your favor – giving you a good indication of the edge measured.

Take all the trades generated by the entry signal.
Close each trade after a given duration of n days.
Calculate the e-ratio based on data from all trades (formula detailed in 4 steps below). This gives you the e-ratio for a trade duration of n days.
Repeat the operation for various values of n to chart the e-ratio curve as a function of the number n of days – as illustrated below:



The e-ratio of the entry criteria is plotted above. The higher the value of the e-ratio, the better the edge. In the instance above the 45-day e-ratio is 1.21 but drops to 1.07 for day 68.


Step 1: Record MAE and MFE for each trade

For each trade, measure the Maximum Favorable Excursion and the Maximum Adverse Excursion.
Maximum Excursions are the maximum amount the price goes against you (Adverse) or in your favor (Favorable) during the trade. MAE is calculated between the entry price and the lowest price during the trade. MFE is calculated between the entry price and the highest price during the trade. Note that both values are positive.
Step 2: Normalise MAE and MFE values

To be able to compute the e-ratio across different markets, the Excursion values should be normalised to a common denominator – such as a unit of volatility. The Average True Range is a good measure of volatility. In many systems it is also used to drive the position sizing, making it really relevant.
Divide all MAE and MFE values by the ATR calculated at the beginning of the trade. In this example we use the same period for the ATR and the Donchian Channel.
This gives you comparable values across all markets and conditions.
Step 3: Average MAE and MFE values across all trades

Simple maths here: just add all normalised MAE values calculated in step 2 and divide by the number of trades. Repeat the operation for the MFE values.
Step 4: Final division = e-ratio

Simply divide the average MFE by the average MAE to give you the e-ratio. The higher the number, the better, with any values above 1 implying a positive edge.
Analysis

Plotting the e-ratio across different durations allows you to check the edge offered by the signal and what timeframe works best for the signal parameters.

You can also combine e-ratios for different parts of a system to see how they impact each other.
Another component of a trading system could be a trade filter, for example, trade with the main trend:

Only buy when the moving average (at a higher timeframe) is rising and below the price.
Only sell when the moving average (at a higher timeframe) is declining and above the price


http://www.automated-trading-system.com/e-ratio-trading-edge/






//----------------------------------------------------------------------
// e-ratio code aggregated by Jez Liberty
// http://www.automated-trading-system.com
//
// The code is largely inspired from the ASX Gorilla blog
// http://theasxgorilla.blogspot.com/2007/07/how-to-compute-edge-ratio-in-amibroker.html
//
// implementation of the Edge Ratio, included below, involves two profound Amibroker fudges.
// The first is the use of the AddToComposite function to create a composite ticker symbol
// in which to hold the ATR array of a given stock for later retrieval within the Custom Back Tester
// via the Foreign function.
// The second fudge is the use of the VarSet/VarGet function to create a quasi array.
// This was necessary to overcome the limitation where array elements cannot exceed in number the value of barcount-1.
//----------------------------------------------------------------------


//---------------------------------------------------------------------------------------------------------
// Options default reset (taken from boilerplate.afl on AmibrokerU.com
// Should be included on all code files
//---------------------------------------------------------------------------------------------------------

SetOption("InitialEquity",1000);
SetOption("MinShares", .0001);
SetOption("MinPosValue",0);
SetOption("FuturesMode", False);
SetOption("AllowPositionShrinking", True);
SetOption("ActivateStopsImmediately",False);
SetOption("ReverseSignalForcesExit", True);
SetOption("AllowSameBarExit",True);
SetOption("CommissionMode", 2);
SetOption("CommissionAmount", 0);
SetOption("InterestRate", 0);
SetOption("MarginRequirement", 100);
SetOption("PortfolioReportMode",0);
SetOption("MaxOpenPositions", 1);
SetOption("WorstRankHeld", 1);// Not in settings
SetOption("PriceBoundChecking",False);// Not in settings
SetOption("UsePrevBarEquityForPosSizing",True);
SetOption("UseCustomBacktestProc",False);

SetOption("DisableRuinStop",False);// Not in settings
SetOption("EveryBarNullCheck",False);// Not in settings

SetOption("HoldMinBars",0);// Not in settings
SetOption("HoldMinDays",0);// Not in settings
SetOption("EarlyExitBars",0);// Not in settings
SetOption("EarlyExitDays",0);// Not in settings
SetOption("EarlyExitFee",0);// Not in settings

SetOption("SeparateLongShortRank",False);// Not in settings
SetOption("MaxOpenLong",0);// Not in settings
SetOption("MaxOpenShort",0);// Not in settings

MaxPos= 100 * 100 / GetOption("MarginRequirement");
PositionSize = -MaxPos / GetOption("MaxOpenPositions");

RoundLotSize = 1; // 0 for Funds, 100 for Stocks
TickSize= 0; // 0 for no min. size
MarginDeposit = 10;
PointValue= 1;// For futures

ExitAtTradePrice = 0;
ExitAtStop= 1;
ExitNextBar= 2;

ReEntryDelay= 0;

//---------------------------------------------------------------------------------------------------------
// End of options reset - override options below
//---------------------------------------------------------------------------------------------------------

//Override of options to enable e-ratio calc and multiple simultaneous positions
PosQty = 5; // You can define here how many open positions you want
SetOption("MaxOpenPositions", PosQty );
PositionSize = -100/PosQty; // invest 100% of portfolio equity divided by max. position count
SetOption("InitialEquity",10000000);
SetOption("FuturesMode", True);

//-------------------------------------------------------------------------------
//Actual System/Signal tested goes below:
//-------------------------------------------------------------------------------

//BUY RULES: implemented with a Buy Stop based Upper Donchian Channel(20)
BuyStop = Ref(HHV(High, 20),-1);
Buy = Cross( High, BuyStop );
BuyPrice = Max( BuyStop, Low ); // make sure buy price not less than Low

//------------------------------------------------------------------------------
//e-ratio specific code
//------------------------------------------------------------------------------
//eratio is the variable that we "optimise" (step from 1 to 100)
eratio = Optimize("Eratio", 20, 1, 100, 1);

//Never Sell so that the position is stopped out after N bar instead
Sell = 3 > 5;
//Stop the positon and close it after N bars (eratio = N that we step from 1 to 100 in optimisation)
ApplyStop( stopTypeNBar, stopModeBars, eratio );

//AddToComposite function is used to create a composite ticker symbol.
//In it we hold the ATR array of a given instrument
//This is for later retrieval within the Custom Back Tester via the Foreign function
Normaliser = ATR(20);
AddToComposite(Normaliser, "~atr_"+Name(), "C", 1+2+8);

SetCustomBacktestProc(""); //activate the custom backtester
if(Status("action") == actionPortfolio) //called when backtesting/optimising
{
bo = GetBacktesterObject();
bo.PreProcess(); // run default backtest procedure
TradeATR = NumTrades = ATRArr = 0; //init variables
for( bar=0; bar < BarCount-1; bar++) { bo.ProcessTradeSignals(bar); for ( sig=bo.GetFirstSignal(bar); sig; sig=bo.GetNextSignal(bar) ) { if (sig.isEntry()) { NumTrades++; ATRArr = Foreign("~atr_"+sig.Symbol, "C"); VarSet("TradeATR" + NumTrades, ATRArr[bar]); _TRACE("Symbol " + sig.Symbol + " ATR: " + VarGet("TradeATR" + NumTrades)); } } } AvgMAE = AccumMAE = AvgMFE = AccumMFE = NumTrades = 0; // iterate through closed trades for( trade = bo.GetFirstTrade(); trade; trade = bo.GetNextTrade() ) { NumTrades++; EntryATR = VarGet ("TradeATR" + NumTrades); if ( EntryATR != 0 ) { _TRACE("EntryATR: " + WriteVal(EntryATR)); _TRACE("AccumMAE : " + WriteVal(AccumMAE)); AccumMAE = AccumMAE + (trade.GetMAE()*trade.EntryPrice/(100*EntryATR)); AccumMFE = AccumMFE + (trade.GetMFE()*trade.EntryPrice/(100*EntryATR)); } trade.AddCustomMetric("My MAE", trade.GetMAE()*trade.EntryPrice/100); trade.AddCustomMetric("My MFE", trade.GetMFE()*trade.EntryPrice/100); trade.AddCustomMetric("Entry ATR", EntryATR*10000); } AvgMAE = AccumMAE / NumTrades; AvgMFE = AccumMFE / NumTrades; _TRACE(WriteVal(AccumMAE )); _TRACE(WriteVal(NumTrades)); _TRACE(WriteVal(AvgMAE)); Eratio = abs(AvgMFE/AvgMAE); _TRACE(WriteVal(Eratio)); bo.AddCustomMetric( "Avg MAE", AvgMAE ); bo.AddCustomMetric( "Avg MFE", AvgMFE ); bo.AddCustomMetric( "Eratio", Eratio); bo.PostProcess(); } http://www.automated-trading-system.com/e-ratio-amibroker-code/

No comments:

My Blog List

Total Pageviews

Search This Blog

Followers