1 votos

¿Qué es lo que falla en este backtester de python?

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?

1voto

Matthew Cole Puntos 697

En esta línea se obtiene un producto cruzado en lugar de una multiplicación valor a valor:

cartera = posiciones*precio['precio']

Sospecho que necesitas algo así (usar el archivo .position de tu dataframe) :

portfolio = positions['position']*price['price']    
pos_diff = positions['position'].diff()

#creating holidings
portfolio['holidings'] = (positions['position']*price['price']).sum()
portfolio['cash'] = initial_capitalpos_diff*price['price']).sum().cumsum()
....

Finanhelp.com

FinanHelp es una comunidad para personas con conocimientos de economía y finanzas, o quiere aprender. Puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X