Есть ли способ получить несколько результатов на np.where? - PullRequest
2 голосов
/ 16 июня 2019

Поэтому я решил недавно изучить 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()    
...