I found some code to calculate the Sharpe as a custom metric but cannot find anything re how to calculate the Sharpe based on B&H.
Also, how do I reference the "SharpeRatio2" in the positionscore function, assuming I can calculate SharpeRatio2 on the B&H of the symbol?

SetCustomBacktestProc("");
if( Status("action") == actionPortfolio )
{
bo = GetBacktesterObject();
bo.Backtest(); // run default backtest procedure
st = bo.GetPerformanceStats(0); // get stats for all trades
eq = bo.EquityArray;
SharpeRatio2 = st.GetValue("CAR")/(sqrt(252)*StDev(((eq-Ref(eq,-1))/Ref(eq,-1))*100, BarCount -2 ));
Here we add custom metric to backtest report
bo.AddCustomMetric( "SharpeRatio2", LastValue(SharpeRatio2) );
StaticVarSet("MySharpe", SharpeRatio2 );
}
SetBacktestMode( backtestRotational );
SetOption("MaxOpenPositions",5);
SetOption("WorstRankHeld",5);
SetPositionSize( 20, spsPercentOfEquity );
PositionScore = ROC( Close, 3):

Maybe look in this direction... I tried it, but it gave an "inf" sharpe... but I did not test it extensively. Maybe you get it working (don't forget to let us know)

Thanks Henri. I did see this on the Report so I guess the stat is available but not sure how to calculate and call it in a script for each & every symbol in a Watchlist.

@reds You want to rank your securities by Sharpe Ratio instead of ROC. The number you are getting in the above code or from AmiBroker (will give you the Sharpe Ratio of trades) is probably only available to you after you run a backtest.

All you need is to replace your ROC(C, 3) with a formula for calculating the Sharpe Ratio of your securities, bar-by-bar. That can be found in hundreds of places on the internet. If you want to start with the original author The Sharpe Ratio

Simplified,

But I think that for your needs you can further simplify because the â€śRisk Free Rate of Returnâ€ť is going to be the same for all securities that you are doing the calculation upon so really you only need,

Rate of Return / St Deviation of Rate of Return

And use that to do your ranking. Coded it might look something like this

// you wrote that you want a Buy & Hold Sharpe, so I assume as it would
// be measured from the first bar you are analyzing
BarsInAnalysis = Cum( Status( "barinrange" ) );
avDailyRt = MA(ROC(C, 1), BarsInAnalysis);
sdDailyRt = StDev( ROC(C, 1), BarsInAnalysis);
// not a real Sharpe ratio but an estimate for comparison purposes
sRatio = ( avDailyRt /sdDailyRt ) * sqrt( 252 ); // annualizing the daily measure

Or perhaps you are using Monthly bars instead of Daily? ( "ROC(C,3)" )

// or if you are using monthly data
sRatio = ( avDailyRt /sdDailyRt ) * sqrt( 12 ); // annualizing the Monthly measure

Larry your code works perfectly, ranking and taking positions by Sharpe.

With rotational trading, can we condition the code to only go long (buy) when the Sharpe is >1? In the below I added "+100" to the Sharpe ratio so it will only go long, but it does not accomplish only buying when the sRatio is >1 since it holds the top 5 and the top 5 may be below 1.

Thanks,

Mike

BarsInAnalysis = Cum( Status( "barinrange" ) );
avDailyRt = MA(ROC(C, 1), BarsInAnalysis);
sdDailyRt = StDev( ROC(C, 1), BarsInAnalysis);
// not a real Sharpe ratio but an estimate for comparison purposes
sRatio = ( avDailyRt /sdDailyRt ) * sqrt( 252 ); // annualizing the daily measure
SetBacktestMode( backtestRotational );
SetOption("MaxOpenPositions",10);
SetOption("WorstRankHeld",10);
SetPositionSize( 10, spsPercentOfEquity );
PositionScore = sRatio+100;

The score (PositionScore) for all securities is calculated first. Then all scores are sorted according to absolute value of PositionScore. Then top N are choosen to be traded. N depends on available funds and "max. open positions" setting. Backtester successively enters the trades starting from highest ranked security until the number of positions open reaches "max. open positions" or there are no more funds available. The score has the following meaning:

higher positive score means better candidate for entering long trade

lower negative score means better candidate for entering short trade

the score of zero means no trade (exit the trade if there is already open position on given symbol)

the score equal to scoreNoRotate constant means that already open trades should be kept and no new trades entered

the score equal to scoreExitAll constant causes rotational mode backtester to exit all positions regardless of HoldMinBars. Note that this is global flag and it is enough to set it for just any single symbol to exit all currently open positions, no matter on which symbol you use scoreExitAll (it may be even on symbol that is not currently held). By setting PositionScore to scoreExitAll you exit all positions immediatelly regardless of HoldMinBars setting

PositionScore = Iif(sRatio>1, sRatio+100, 0);

Not true. It is not a single number.
It can be retrieved on bar-by-bar basis.