Dans Article précédent, nous avons collecté des données FX passées à l'aide de l'API REST OANDA. Cette fois, sur la base de ces données, nous décrirons la méthode d'évaluation stratégique du bot de trading automatique d'investissement. TL; DR → documentation de backtesting
C'est juste ↓
pip install backtesting
On suppose que la base de données appelée ʻusd_jpy_4hcontient les données acquises dans [Article précédent](https://qiita.com/k_0/items/e36162b9c623d27583c9). Nous utilisons également
talib`, un package d'analyse technique. Cela peut également être facilement abandonné avec pip.
La documentation talib est ici [https://mrjbq7.github.io/ta-lib/doc_index.html)
import talib as ta
import pandas as pd
from backtesting import Backtest, Strategy
from backtesting.lib import crossover
import db_access
def get_raw_data(query):
engine = db_access.get_engine()
return pd.read_sql(query, engine)
def get_macd(close, fastperiod=6, slowperiod=13, signalperiod=4):
macd, macdsignal, macdhist = ta.MACD(close, fastperiod=fastperiod, slowperiod=slowperiod, signalperiod=signalperiod)
return macd, macdsignal, macdhist
query = "select distinct * from usd_jpy_4h where datetime between '2019/09/01' and '2020/03/01' order by datetime"
raw_data = get_raw_data(query)
df = raw_data[["datetime","open","high","low","close","volume"]].copy()
df.columns = ['Datetime', 'Open', 'High', 'Low', 'Close', 'Volume']
df['Datetime'] = pd.to_datetime(df['Datetime'])
df = df.reset_index().set_index('Datetime')
class MacdStrategy(Strategy):
macd_fastperiod = 6
macd_slowperiod = 13
macd_signalperiod = 4
profit_pips = 50
loss_pips = 50
profit = profit_pips * 0.01
loss = loss_pips * 0.01
def init(self):
self.macd, self.signal, self.hist = self.I(get_macd, self.data.Close, self.macd_fastperiod, self.macd_slowperiod, self.macd_signalperiod)
def next(self):
if (crossover(self.signal, self.macd)):
self.buy(sl=self.data.Close[-1] - self.loss, tp=self.data.Close[-1] + self.profit)
elif (crossover(self.macd, self.signal)):
self.sell(sl=self.data.Close[-1] + self.loss, tp=self.data.Close[-1] - self.profit)
bt = Backtest(df, MacdStrategy, cash=100000, commission=.00004)
output = bt.run()
print(output)
output
Start 2019-09-01 20:00:00
End 2020-02-28 20:00:00
Duration 180 days 00:00:00
Exposure [%] 74.9074
Equity Final [$] 98647
Equity Peak [$] 101404
Return [%] -1.35297
Buy & Hold Return [%] 1.81654
Max. Drawdown [%] -2.7724
Avg. Drawdown [%] -0.518637
Max. Drawdown Duration 162 days 00:00:00
Avg. Drawdown Duration 21 days 18:00:00
# Trades 66
Win Rate [%] 50
Best Trade [%] 0.457344
Worst Trade [%] -0.68218
Avg. Trade [%] -0.0215735
Max. Trade Duration 10 days 00:00:00
Avg. Trade Duration 2 days 02:00:00
Expectancy [%] 0.275169
SQN -0.538945
Sharpe Ratio -0.0655224
Sortino Ratio -0.107821
Calmar Ratio -0.00778153
_strategy MacdStrategy
dtype: object
raw_data = get_raw_data(query)
df = raw_data[["datetime","open","high","low","close","volume"]].copy()
df.columns = ['Datetime', 'Open', 'High', 'Low', 'Close', 'Volume']
df['Datetime'] = pd.to_datetime(df['Datetime'])
df = df.reset_index().set_index('Datetime')
Ici, les données de la base de données sont acquises et formatées pour le backtesting. En backtestin, je m'attends à ce que les noms de colonne soient'Open ',' High ',' Low ',' Close ',' Volume '(OK sans cela) dans le pandas Dataframe. Il est également recommandé d'ajouter un index avec le type datetime. https://kernc.github.io/backtesting.py/doc/examples/Quick%20Start%20User%20Guide.html
You bring your own data. Backtesting ingests data as a pandas.DataFrame with columns 'Open', 'High', 'Low', 'Close', and (optionally) 'Volume'. Such data is easily obtainable (see e.g. pandas-datareader, Quandl, findatapy, ...). Your data frames can have other columns, but these are necessary. DataFrame should ideally be indexed with a datetime index (convert it with pd.to_datetime()), otherwise a simple range index will do.
class MacdStrategy(Strategy):
macd_fastperiod = 6
macd_slowperiod = 13
macd_signalperiod = 4
profit_pips = 50
loss_pips = 50
profit = profit_pips * 0.01
loss = loss_pips * 0.01
def init(self):
self.macd, self.signal, self.hist = self.I(get_macd, self.data.Close, self.macd_fastperiod, self.macd_slowperiod, self.macd_signalperiod)
def next(self):
if (crossover(self.signal, self.macd)):
self.buy(sl=self.data.Close[-1] - self.loss, tp=self.data.Close[-1] + self.profit)
elif (crossover(self.macd, self.signal)):
self.sell(sl=self.data.Close[-1] + self.loss, tp=self.data.Close[-1] - self.profit)
La stratégie d'achat et de vente est créée en héritant de «la stratégie d'importation de backtesting».
Cette fois, j'écris un programme avec une stratégie d'achat et de vente lorsque Macd, qui est l'un des indicateurs techniques, croise.
Dans les stratégies d'investissement, de nombreuses stratégies se déclenchent lorsqu'une courbe de série chronologique en croise une autre. Vous pouvez facilement décrire la stratégie en utilisant crossover ()
.
https://kernc.github.io/backtesting.py/doc/backtesting/lib.html#backtesting.lib.crossover
Il existe de nombreuses autres fonctionnalités utiles, veuillez donc consulter la documentation.
stats = bt.optimize(
macd_fastperiod = [6, 8, 10, 12],
macd_slowperiod = [13, 19, 26],
macd_signalperiod = [4, 7, 9],
profit_pips = [30, 50, 70, 90],
loss_pips = [20, 30, 40, 50]
)
En utilisant Backtest.optimize ()
, vous pouvez tester la valeur / combinaison optimale pour les variables utilisées dans la stratégie d'achat et de vente.
Ici, la valeur décidée à la main est définie dans une certaine mesure, mais elle peut être définie sous la forme de «[i pour i dans la plage (10)]» (bien que cela semble être un traitement lourd).
Les paramètres optimaux peuvent être confirmés avec stats._strategy
après avoir exécuté Optimize ().
Recommended Posts