Estoy tratando de escribir un simple backtester utilizando python y pandas. He reutilizado el código de Michael halls moore's pandas backtester. Reescribí el programa porque, en primer lugar, quiero entender cómo funciona el backtesting y, en segundo lugar, encontré (para mí) el código original difícil de entender.
Este es el código reescrito
import datetime
import pandas as pd
import numpy as np
from pandas.io.data import DataReader
#download data
start=datetime.datetime(2000,1,1)
end=datetime.datetime(2012,1,1)
ibm = DataReader('IBM', 'yahoo', start ,end )
#technical analysis library
#https://www.quantopian.com/posts/technical-analysis-indicators-without-talib-code
def MA(df, n):
MA = pd.Series(pd.rolling_mean(df, n), name = 'MA_' + str(n))
df =MA
return df
def gen_signals(df,fast=10,slow=30):
signals=pd.DataFrame(index=df.index)
signals['signal']=0
signals['price']=df
#fast slow moving average
signals['fast']=MA(signals['price'],fast)
signals['slow']=MA(signals['price'],slow)
#if fast sma is greater than slow sma then 1 else 0
signals['signal']=np.where(signals['fast']>signals['slow'],1,0)
#taking difference to genrate actual trading order
signals['positions']=signals['signal'].diff()
return signals
def gen_positions(self):
positions=pd.DataFrame(index=self.index).fillna(0.0)
positions['position']=10*self['signal'] #10 shares/signal
return positions
def backtest(positions,price,initial_capital=10000):
#creating protfolio
portfolio =positions*price['price']
pos_diff=positions.diff()
#creating holidings
portfolio['holidings']=(positions*price['price']).sum(axis=1)
portfolio['cash']=initial_capital-(pos_diff*price['price']).sum(axis=1).cumsum()
#full account equity
portfolio['total']=portfolio['cash']+ portfolio['holidings']
portfolio['return']=portfolio['total'].pct_change()
return portfolio
#signal generation
sig=gen_signals(ibm['Close'],fast=5,slow=25)
sig.head(3)
#positon genration
pos=gen_positions(sig)
pos.tail(3)
#backtesting
re=backtest(pos,sig)
re.head()
Pero el resultado es este
2011-12-30 00:00:00 position holidings cash total return
Date
2000-01-03 NaN NaN NaN NaN NaN NaN
2000-01-04 NaN NaN NaN NaN NaN NaN
2000-01-05 NaN NaN NaN NaN NaN NaN
2000-01-06 NaN NaN NaN NaN NaN NaN
2000-01-07 NaN NaN NaN NaN NaN NaN
¿Alguna idea de por qué ocurre esto?