Strangely, one of the biggest factors for maximising your returns is accurately calculating the size of the position you want to take after your system has found something to buy. From personal experience, position sizing has made a massive difference to my returns as well as limiting me to an exceptable risk.
I commonly use two types of position sizing - if I have just started investing in a system and am still lacking in confidence as to its long-term viability (backtesting withstanding), I will use one based upon Average True Range. If I have a system I feel confident in and am less risk-averse I will use a system based upon Kelly's F. I will expand upon ATR now and will cover Kelly's F in more detailed in a future article.
ATR Position Sizing
Average True Range was developed by the famous technical analyst and trader, Welles Wilder Jr. It is an indicator of price volatility and its use to us is in factoring the amount we invest based upon the recent volatility of the share price. This method of position sizing has been widely promoted by Turtle Traders - for a summary of how they use it, read the following
PDF. In order to use ATR we need to calculate it for the last
x days - I use 20 days, this seems to be quite a common value. I loop through the current price range I have in my back-testing model with the following code:
var catr = new CalcAverageTrueRange();
var atr = new List<decimal>();
foreach (Price p in thisEpicsPrices)
{
atr.Add(catr.CalcATR(ATRDays, p.High, p.Low, prvClose));
prvClose = p.Close;
}
The
CalcATR function is 'hand-rolled' version adapted to C# from a Metastock formula:
public decimal CalcATR(int days, decimal high, decimal low, decimal previousClose)
{
decimal highMinusLow = high - low;
decimal highMinusPrvClose = Math.Abs(high - previousClose);
decimal lowMinusPrvClose = Math.Abs(low - previousClose);
decimal tr = Math.Max(lowMinusPrvClose, Math.Max(highMinusLow, highMinusPrvClose));
if (_atrCount < days)
{
if (previousClose > 0)
_trTotal += tr;
}
if (_atrCount == days)
{
_lastatr = _trTotal / days;
_atrCount++;
return Math.Round(_lastatr, 2);
}
if (_atrCount > days)
{
_lastatr = (((_lastatr * (days - 1)) + tr) / days);
_atrCount++;
return Math.Round(_lastatr, 2);
}
_atrCount++;
return 0;
}
Hopefully the parameters are self explanatory. From the array that is returned, that latest date is the last value (assuming you are using this in a 'live' system). I have to do one small conversion before I use it and that is to convert it to 'n' (same as the Turtle Traders use):
decimal n = atr[i] / 100; //Convert today's atr to 'n'
I then calculate the number to shares to purchase with the following line of code:
noStocksHeld = (int)(positionSizeValue / (2 * n));
I calculate
positionSizeValue as being my total asset value (all the shares I currently own multiplied by the current price), and how much I have in cash. I then multiply this by a risk factor - I use 1%. Simply, this formula limits the amount you invest in this share based on its current volatility - the more volatile the share, the less it will let you invest. The value 'n' is also used to generate stop-losses, however I use different techniques.