Jag har en utmaning vad gäller att beräkna positionsstorlek som
använder en relativt balanserad kapitalallokering beroende på antalet
positioner man har just nu.
Igår var det "back to school" med gammal hederlig algebra för att komma
på en formel som fungerar. Den är säkert inte perfekt men bättre än vad
jag hade tidigare.
Obs ! För personer med allergi mot matte, scrolla till scripting
Formel för att balansera allokering av kapital till nya positioner i
en portfölj med redan existerande innehav:
c(n) = c(n-1) - ( 1/(p-(n-1)) ) * c(n-1); c(n) går från n=1 till p och n <= p.
där
c(n) = Mängden pengar på kontot just nu
c(n-1) = Mängden pengar på kontot efter plus en position
p = max. antal tillåtna samtidiga positioner. Sätts själv, dvs. begynnelsevillkor.
Exempel:
Jag har för tillfället inga positioner i min depå.
Maximalt antal tillåtna samtidiga positioner i depån är 5.
Jag får köpsignal och ska ta en första position.
Startsumman c(0) är 100.000 SEK.
Detta betyder att beräkningen av allokeringen av pengar blir:
Position 1:
Sätt a = ( 1/(p-(n-1) ) * c(n-1)
c(1) = c(1-1) - a ->
c(1) = c(0) - (1/(5-(1-1)) ) * c(1-1) ->
c(1) = c(0) - (1/5) * c(0) = 100.000 - (1/5) * 100.000 = 80.000 SEK
och a = (1/5) * 100.000 = 20.000 SEK
Dvs. för första positionen allokeras 20.000 SEK av totala mängden pengar som är 100.000 SEK.
Kvarvarande mängd pengar är nu c(1) = 80.000 SEK.
Position 2:
Sätt a = ( 1/(p-(n-1) ) * c(n-1)
c(2) = c(2-1) - a ->
c(2) = c(1) - (1/(5-(2-1)) ) * c(2-1) ->
c(2) = c(1) - (1/4) * c(1) = 80.000 - (1/4) * 80.000 = 60.000 SEK
och a = (1/4) * 80.000 = 20.000 SEK
Dvs. för andra positionen allokeras 20.000 SEK av totala mängden tillgängliga pengar som är 80.000 SEK.
osv..
Detta sätt balanserar mängden pengar man allokerar för positioner man har för tillfället
i portföljen. Finns säkert bättre sätt, men det fungerar bra nog för mig just nu.
Notera också att nämnaren i uttrycket 1/(p-(n-1) går från värdet på
max. antal tillåtna positioner (p) till 1.
Väljer man 5 som max blir alltså uttrycket 1/5, 1/4, .. , 1/1.
Väljer man 10 som max blir uttrycket 1/10, 1/9, .. , 1/1.
Slut på mattelektionen. Pusta ut och läs vidare.
Jag har lyckats testa i kalkylforskaren fram till en position och scriptet
gör så långt som förväntat.
Problemet blir när jag vill kontrollera resten av fallen, med mer än
en position. Jag får då fel i syntaxkontrollen (se screenshot).
Nedan är scriptet som det ser ut just nu. Jag kan inte själv
se vad jag gör för fel, men förhoppningsvis kan mer erfarna
scriptgurus här på forumet hjälpa till.
/Robban
Script:
{ ---- Start test position size with portfolio balance formula ---- }
{ ----- Start first stock, large initstop candlestick ------ }
{ test different commissions }
low:=26000
{ simulated account, entry and initstops }
account:=80000 { Change to cash(n) when going live. Test cases: Use 100k, 80k, 60k, 40k, 20k, and 1k to simulate 0-5 positions and lack of funds. }
total:=100000 { Change to cash(a) when going live. Test case: total assets using 100000 SEK in total net worth. }
entry:=o { Test cases: Use opening price and current sell price. }
price:=c
init:=getgvar(100) { Test cases: Use getgvar(100-109) for all initstop variants. }
{ ----- End first stock, large initstop candlestick ------ }
{ test calculation using 100 units }
units:=100
exposure:=mult(units,price)
{ If exposure is above 26000, use percentage based commissions, else 59 sek. }
percentage:=mult(exposure,0.0015)
small:=59
comselect:=if(gt(exposure,low),percentage,small)
{ position size formula (assuming the 1R risk is 1%): PS = INT( ((A·0.01) - C) / abs(E-I) ) }
{ Maximum loss: A·0.01 }
mloss:=mult(account,0.01)
{ Risk per unit: abs(E-I) }
rpu:=abs(sub(entry,init))
ps:=int(div(sub(mloss,comselect),rpu))
{ Check if the amount of cash equals cash+positions. If true, I have only cash at the moment which means i have no positions open }
checkPos:=if(eqv(account,total),allocate1,hasPos1) { Test cases: In false position, use ps to test no positions and use hasPos1 to test having existing positions. }
{ If i have no positions, allocate 1/5 of the cash to the first position }
allocate1:=mult(0.2,account)
{ Remaining cash after taking one position. }
one:=sub(account,allocate1)
{ Check if 4/5 or less and 3/5 or more is in cash and 1/5 or more is in positions. If true, i have one position at the moment }
hasPos1:=if(and(le(account,one),gt(account,mult(0.6,total))),allocate2,hasPos2)
{ If i have one position, allocate 1/4 of the remaining cash to the second position }
allocate2:=mult(0.25,account)
{ Remaining cash after taking a second position. }
two:=sub(account,allocate2)
{ Check if 3/5 or less and 2/5 or more is in cash and 2/5 or more is in positions. If true, i have two positions at the moment }
hasPos2:=if(and(le(account,two),gt(account,mult(0.4,total))),allocate3,hasPos3)
{ If i have two positions, allocate 1/3 of the remaining cash to the third position. }
allocate3:=mult(0.33,account)
{ Remaining cash after taking a third position. }
three:=sub(account,allocate3)
{ Check if 2/5 or less and 1/5 or more is in cash and 3/5 or more is in positions. If true, i have three positions at the moment. }
hasPos3:=if(and(le(account,three),gt(account,mult(0.2,total))),allocate4,hasPos4)
{ If i have three positions, allocate 1/2 of the remaining cash to the fourth position. }
allocate4:=mult(0.5,account)
{ Remaining cash after taking a fourth position. }
four:=sub(account,allocate4)
{ Check if 1/5 or less and 1000 SEK or more is in cash and 4/5 or more is in positions. If true, i have four positions at the moment. }
hasPos4:=if(and(le(account,four),gt(account,1000)),allocate5,max)
{ If i have four positions, allocate 1/1 of the remaining cash minus 1000 SEK for unexpected costs to the fifth position. }
allocate5:=sub(account,1000)
{ Remaining cash after taking a fifth position. }
five:=account
{ If i have five positions then do nothing, else go back and check how many positions i currently have. }
max:=if(le(account,five),0,checkPos)
{ Adjust if the stock price times the position size is larger than 20% of the account: positionSize = (accountSize*0.20 - commissions) / entryPrice; positionSize = (int)(positionSize); }
adjust=int(div(sub(checkPos,comselect),entry))
{ Check if the stock price times the position size is larger than 20% of the account: if( (positionSize*stockPrice) > accountSize*0.20 ) }
new=if(gt(mult(ps,c),mult(account,0.2)),adjust,ps)
new
{ ---- End test position size with portfolio balance formula ---- }
använder en relativt balanserad kapitalallokering beroende på antalet
positioner man har just nu.
Igår var det "back to school" med gammal hederlig algebra för att komma
på en formel som fungerar. Den är säkert inte perfekt men bättre än vad
jag hade tidigare.
Obs ! För personer med allergi mot matte, scrolla till scripting
Formel för att balansera allokering av kapital till nya positioner i
en portfölj med redan existerande innehav:
c(n) = c(n-1) - ( 1/(p-(n-1)) ) * c(n-1); c(n) går från n=1 till p och n <= p.
där
c(n) = Mängden pengar på kontot just nu
c(n-1) = Mängden pengar på kontot efter plus en position
p = max. antal tillåtna samtidiga positioner. Sätts själv, dvs. begynnelsevillkor.
Exempel:
Jag har för tillfället inga positioner i min depå.
Maximalt antal tillåtna samtidiga positioner i depån är 5.
Jag får köpsignal och ska ta en första position.
Startsumman c(0) är 100.000 SEK.
Detta betyder att beräkningen av allokeringen av pengar blir:
Position 1:
Sätt a = ( 1/(p-(n-1) ) * c(n-1)
c(1) = c(1-1) - a ->
c(1) = c(0) - (1/(5-(1-1)) ) * c(1-1) ->
c(1) = c(0) - (1/5) * c(0) = 100.000 - (1/5) * 100.000 = 80.000 SEK
och a = (1/5) * 100.000 = 20.000 SEK
Dvs. för första positionen allokeras 20.000 SEK av totala mängden pengar som är 100.000 SEK.
Kvarvarande mängd pengar är nu c(1) = 80.000 SEK.
Position 2:
Sätt a = ( 1/(p-(n-1) ) * c(n-1)
c(2) = c(2-1) - a ->
c(2) = c(1) - (1/(5-(2-1)) ) * c(2-1) ->
c(2) = c(1) - (1/4) * c(1) = 80.000 - (1/4) * 80.000 = 60.000 SEK
och a = (1/4) * 80.000 = 20.000 SEK
Dvs. för andra positionen allokeras 20.000 SEK av totala mängden tillgängliga pengar som är 80.000 SEK.
osv..
Detta sätt balanserar mängden pengar man allokerar för positioner man har för tillfället
i portföljen. Finns säkert bättre sätt, men det fungerar bra nog för mig just nu.
Notera också att nämnaren i uttrycket 1/(p-(n-1) går från värdet på
max. antal tillåtna positioner (p) till 1.
Väljer man 5 som max blir alltså uttrycket 1/5, 1/4, .. , 1/1.
Väljer man 10 som max blir uttrycket 1/10, 1/9, .. , 1/1.
Slut på mattelektionen. Pusta ut och läs vidare.
Jag har lyckats testa i kalkylforskaren fram till en position och scriptet
gör så långt som förväntat.
Problemet blir när jag vill kontrollera resten av fallen, med mer än
en position. Jag får då fel i syntaxkontrollen (se screenshot).
Nedan är scriptet som det ser ut just nu. Jag kan inte själv
se vad jag gör för fel, men förhoppningsvis kan mer erfarna
scriptgurus här på forumet hjälpa till.
/Robban
Script:
{ ---- Start test position size with portfolio balance formula ---- }
{ ----- Start first stock, large initstop candlestick ------ }
{ test different commissions }
low:=26000
{ simulated account, entry and initstops }
account:=80000 { Change to cash(n) when going live. Test cases: Use 100k, 80k, 60k, 40k, 20k, and 1k to simulate 0-5 positions and lack of funds. }
total:=100000 { Change to cash(a) when going live. Test case: total assets using 100000 SEK in total net worth. }
entry:=o { Test cases: Use opening price and current sell price. }
price:=c
init:=getgvar(100) { Test cases: Use getgvar(100-109) for all initstop variants. }
{ ----- End first stock, large initstop candlestick ------ }
{ test calculation using 100 units }
units:=100
exposure:=mult(units,price)
{ If exposure is above 26000, use percentage based commissions, else 59 sek. }
percentage:=mult(exposure,0.0015)
small:=59
comselect:=if(gt(exposure,low),percentage,small)
{ position size formula (assuming the 1R risk is 1%): PS = INT( ((A·0.01) - C) / abs(E-I) ) }
{ Maximum loss: A·0.01 }
mloss:=mult(account,0.01)
{ Risk per unit: abs(E-I) }
rpu:=abs(sub(entry,init))
ps:=int(div(sub(mloss,comselect),rpu))
{ Check if the amount of cash equals cash+positions. If true, I have only cash at the moment which means i have no positions open }
checkPos:=if(eqv(account,total),allocate1,hasPos1) { Test cases: In false position, use ps to test no positions and use hasPos1 to test having existing positions. }
{ If i have no positions, allocate 1/5 of the cash to the first position }
allocate1:=mult(0.2,account)
{ Remaining cash after taking one position. }
one:=sub(account,allocate1)
{ Check if 4/5 or less and 3/5 or more is in cash and 1/5 or more is in positions. If true, i have one position at the moment }
hasPos1:=if(and(le(account,one),gt(account,mult(0.6,total))),allocate2,hasPos2)
{ If i have one position, allocate 1/4 of the remaining cash to the second position }
allocate2:=mult(0.25,account)
{ Remaining cash after taking a second position. }
two:=sub(account,allocate2)
{ Check if 3/5 or less and 2/5 or more is in cash and 2/5 or more is in positions. If true, i have two positions at the moment }
hasPos2:=if(and(le(account,two),gt(account,mult(0.4,total))),allocate3,hasPos3)
{ If i have two positions, allocate 1/3 of the remaining cash to the third position. }
allocate3:=mult(0.33,account)
{ Remaining cash after taking a third position. }
three:=sub(account,allocate3)
{ Check if 2/5 or less and 1/5 or more is in cash and 3/5 or more is in positions. If true, i have three positions at the moment. }
hasPos3:=if(and(le(account,three),gt(account,mult(0.2,total))),allocate4,hasPos4)
{ If i have three positions, allocate 1/2 of the remaining cash to the fourth position. }
allocate4:=mult(0.5,account)
{ Remaining cash after taking a fourth position. }
four:=sub(account,allocate4)
{ Check if 1/5 or less and 1000 SEK or more is in cash and 4/5 or more is in positions. If true, i have four positions at the moment. }
hasPos4:=if(and(le(account,four),gt(account,1000)),allocate5,max)
{ If i have four positions, allocate 1/1 of the remaining cash minus 1000 SEK for unexpected costs to the fifth position. }
allocate5:=sub(account,1000)
{ Remaining cash after taking a fifth position. }
five:=account
{ If i have five positions then do nothing, else go back and check how many positions i currently have. }
max:=if(le(account,five),0,checkPos)
{ Adjust if the stock price times the position size is larger than 20% of the account: positionSize = (accountSize*0.20 - commissions) / entryPrice; positionSize = (int)(positionSize); }
adjust=int(div(sub(checkPos,comselect),entry))
{ Check if the stock price times the position size is larger than 20% of the account: if( (positionSize*stockPrice) > accountSize*0.20 ) }
new=if(gt(mult(ps,c),mult(account,0.2)),adjust,ps)
new
{ ---- End test position size with portfolio balance formula ---- }
Comment