Поэтому я решил недавно изучить python, чтобы протестировать портфели, и наткнулся на проблему оптимизации времени.
Функция, которую я написал, работает правильно, но требует много времени для вычислений. Я читал, что это должно быть из-за разных петель.
Поэтому я хотел знать, есть ли способ оптимизировать этот код.
Я пытался использовать np.where в первом условии, используя несколько результатов, но он выдал ошибку
РЕДАКТИРОВАТЬ:
Это ошибка
data['cash'] = np.where((data['Position'] == 1) & (data['signal']==1), (data['positions']=data['cash'].iloc[row-1]/data['Close'].iloc[row]*0.9)&(data['cash'].iloc[row] =data['positions'].iloc[row] *data['Close'].iloc[row]), 0)
необходимый импорт
import pandas as pd
import numpy as np
Это простая средняя стратегия кроссовера
def smasig (data, fast_days,slow_days, threshold):
data['FMA'] = data['Close'].rolling(center=False,window=fast_days, min_periods=fast_days).mean()
data['SMA'] = data['Close'].rolling(center=False,window=slow_days, min_periods=slow_days).mean()
data['FMA-SMA'] = data['FMA'] - data['SMA']
Threshold = threshold
data['Position']=0
data['Position'] = np.where(data['FMA']>data['SMA'],1.0,0.0)
data['signal']=data['Position'].diff()
Это функция, которая работает правильно, но я хотел бы оптимизировать
def backtest(data, init):
data['cash'] =0.0
data['positions']=0
initial = init
for row in range(len(data)):
if row == 1:
data['cash']= initial
row+=1
if (data['Position'].iloc[row] == 1) and (data['signal'].iloc[row]==1):
data['positions'].iloc[row]=data['cash'].iloc[row-1]/data['Close'].iloc[row]
data['cash'].iloc[row] =data['positions'].iloc[row] *data['Close'].iloc[row]
elif (data['Position'].iloc[row] == 1) and (data['signal'].iloc[row]==0):
data['positions'].iloc[row] = data['positions'].iloc[row-1]
data['cash'].iloc[row] =data['positions'].iloc[row] *data['Close'].iloc[row]
elif (data['Position'].iloc[row] == 0) and (data['signal'].iloc[row]==-1):
data['positions'].iloc[row] = 0
data['cash'].iloc[row] = data['cash'].iloc[row-1]
elif (data['Position'].iloc[row] == 0) and (data['signal'].iloc[row]==0):
data['positions'].iloc[row] = 0
data['cash'].iloc[row] = data['cash'].iloc[row-1]
(data['Close'] / data['Close'].iloc[1]).plot()
(data['cash']/initial).plot()
Вот экспозиция
GSPC =pd.read_csv(r"C:\Users\****\^GSPC.csv",index_col = "Date",
parse_dates=True, na_values=['nan'])
smasig(GSPC, 7,28,0)
backtest(GSPC,1000)
print(GSPC[['Position','signal', 'cash']].tail(10))
Это будет вывод
В результате я хотел бы получить те же результаты, но в более короткие сроки. Есть ли способ сделать это?
Заранее спасибо за ваше время, и если что-то не понятно, пожалуйста, скажите мне.
Данные о суточных ценах можно загрузить по адресу Yahoo , выбрав дату начала 15.05.2014 и дату окончания 15.05.2009
UPDATE :
Это тот тип кода, который я хотел бы получить, однако он не дает ожидаемых результатов
Ожидаемые результаты
Полученные результаты
def backtest (data, init):
data['cash'] =init
data['positions']=0
initial = init
data['cash'] = np.where(
(data['Position'] == 1) & (data['signal']==1),(
data['positions']==data['cash'].shift(1)/data['Close'])&(
data['cash'] ==data['positions'] *data['Close']),
np.where((data['Position'] == 1) & (data['signal']==0),
(data['positions'] == data['positions'].shift(1))&
(data['cash'] ==data['positions'] *data['Close']),
(data['positions'] == 0)& (data['cash'] == data['cash'].shift(1))))
(data['Close'] / data['Close'].iloc[1]).plot()
(data['cash']/initial).plot()