First of all my goal is not trading but I want to understand how to create a backtest on python.
So my objective is coding only and understanding what is wrong with my code.
I assume that there is no transaction fees and that you can buy a fraction of a stock.
I have this DataFrame:
df=pd.DataFrame({'Date':['2017-05-19','2017-05-22','2017-05-23','2017-05-24','2017-05-25','2017-05-26','2017-05-29'],
'Apple':[153.67,152.76,153.18,155.45,153.93,154.45,155.37],
'Facebook':[139.72,137.43,141,141.55,141.81,142.15,142.06],})
df['Date']=pd.to_datetime(df['Date'])
df = df.set_index('Date')
And I have done my backtest by coding this way:
def backtesting(stock,capital):
df_init=(stock*0).assign(cash=0)
df_end=(stock*0).assign(cash=0)
df_init.iloc[0,df_init.columns.get_loc('cash')]=capital
df_end.iloc[0,df_end.columns.get_loc('cash')]=capital
SMA_2=stock.rolling(2).mean().fillna(0)
SMA_1=stock.rolling(1).mean().fillna(0)
calendar=pd.Series(df_init.index)[1:]
for date in calendar:
for cols in stock:
prev_date=df_init.index[df_init.index<date][-1]
df_init.loc[date,:]=df_end.loc[prev_date,:]
M=2 #number of securities
count = (df_init.loc[date,stock.columns]!=0).sum()
#Weight
if count != M:
weight = 1/(M-count)
else:
weight = 1
#Portfolio
portfolio = stock.loc[date,cols]*df_init.loc[date,cols]+df_init.loc[date,'cash']*weight
#Conditions
if SMA_1.loc[date,cols] > SMA_2.loc[date,cols] and df_init.loc[date,cols]==0:
df_end.loc[date,cols]=portfolio/stock.loc[date,cols]
df_end.loc[date,'cash']=df_init.loc[date,'cash'] - df_end.loc[date,cols]*stock.loc[date,cols]
elif SMA_1.loc[date,cols] > SMA_2.loc[date,cols] and df_init.loc[date,cols]!=0:
df_end.loc[date,cols]=df_init.loc[date,cols]
df_end.loc[date,'cash']=df_init.loc[date,'cash']
else:
df_end.loc[date,cols]=0
df_end.loc[date,'cash']=df_init.loc[date,cols]*stock.loc[date,cols]+df_init.loc[date,'cash']
return df_end
And then in order to see the DataFrame:
backtesting(df,10000)
However this is the problem that I have, when you look at the DataFrame you have this:
Apple Facebook cash
Date
2017-05-19 0.000000 0.000000 10000.000000
2017-05-22 0.000000 0.000000 10000.000000
2017-05-23 32.641337 35.460993 5000.000000
2017-05-24 32.641337 35.460993 5000.000000
2017-05-25 0.000000 35.460993 5000.000000
2017-05-26 32.372936 35.460993 5000.000000
2017-05-29 32.372936 0.000000 10037.588652
And as you can see, my code takes into account the columns Facebook only I still don't understand why.
The result that I expect is this one :
Apple Facebook cash
Date
2017-05-19 0.000000 0.000000 10000.000000
2017-05-22 0.000000 0.000000 10000.000000
2017-05-23 32.641337 35.460993 0
2017-05-24 32.641337 35.460993 0
2017-05-25 0.000000 35.460993 5024.481
2017-05-26 32.372936 35.460993 0
2017-05-29 32.372936 0.000000 5037.58867
I don't have any problem if I only use one stock, but it became a bit difficult with two or more stocks and I would like to know what am I doing wrong.
If somebody has some time and an idea to solve this problem, you are welcome! Thanks
Aucun commentaire:
Enregistrer un commentaire