我正在尝试在 backtrader 上回测一个简单的交易策略,但我不断收到一个错误,指出 pydatetime 没有属性。我试图将日期时间转换为 unix 并返回,但没有太大成功。希望有人可以提出解决办法?我正在从 cryptocompare 中提取比特币数据。
请看下面的代码:
#import libraries
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
import backtrader as bt
import datetime as dt
import requests
import json
import time
#Changing datetime to unix
def from_datetime_to_unix(date):
'''in: datetime, out: unix_timestamp'''
return int(time.mktime(date.timetuple()))
#Getting the Data
BASE_URL = 'https://min-api.cryptocompare.com/data/v2/histoday'
API = 'f2b1bac4cdb7dc8a47f0ebd42987b53beb54cf13441fcd75c4138633495fc292'
PAIR = 'USDT'
headers = {
'Apikey': API
}
def fix_cryptocompare_data(df, drop_cols=None):
"""
Modify cryptocompare df to the required format, checking for wrong entries
and filling nans
"""
df = df.reset_index()
df = df.sort_values(by='time', ascending=False)
assert (df.iloc[0]['time'] - df.iloc[1]['time']) > 0
# Drop unwanted data
if drop_cols:
df = df.drop(drop_cols, axis=1)
# Rename volumeto to volume
# This is volume in the second pair e.g. BTC/USD, volumeto = usd volume of btc
df = df.rename(columns={
'time': 'Datetime',
'open': 'Open',
'high': 'High',
'low': 'Low',
'close': 'Close',
'volumeto': 'Volume'
})
order_cols = ['Datetime', 'Open', 'High', 'Low', 'Close', 'Volume']
df = df[order_cols]
# Forward fill missing values
df.fillna(method='ffill', inplace=True)
return df
def get_data(ticker, start, end):
start = from_datetime_to_unix(dt.datetime.strptime(start, '%d/%m/%Y'))
end = from_datetime_to_unix(dt.datetime.strptime(end, '%d/%m/%Y'))
params = {
'fsym': ticker,
'tsym': PAIR,
'extraParams': 'candle_data',
'aggregate': 4,
'limit': 2000,
'toTs': end
}
response = requests.get(BASE_URL, headers=headers, params=params)
data = json.loads(response.text)
# Create df to join
df = pd.DataFrame(data['Data']['Data'])
ms_start = start
ms_data = data['Data']['TimeFrom']
# While response does not equal start date, keep requesting
while(ms_data > ms_start):
params['toTs'] = ms_data
r = requests.get(BASE_URL, headers=headers, params=params)
data = json.loads(r.text)
# Update ms from new data
ms_data = data['Data']['TimeFrom']
df1 = pd.DataFrame(data['Data']['Data'])
# Join dataframes (appending old to new)
df = df1.append(df)
df = fix_cryptocompare_data(df, drop_cols=['volumefrom', 'conversionType', 'conversionSymbol'])
# Remove dates earlier than start
df = df[df['Datetime'] < start]
return df
#Dates chosen
data = get_data('btc','01/01/2020', '01/01/2021')
# data.iloc[0]['Datetime']
data.iloc[-1]['Datetime']
df = data.copy()
# Create a subclass of SignaStrategy to define the indicators and signals
class SmaCross(bt.SignalStrategy):
# list of parameters which are configurable for the strategy
params = dict(
pfast=10, # period for the fast moving average
pslow=30 # period for the slow moving average
)
def __init__(self):
sma1 = bt.ind.SMA(period=self.p.pfast) # fast moving average
sma2 = bt.ind.SMA(period=self.p.pslow) # slow moving average
crossover = bt.ind.CrossOver(sma1, sma2) # crossover signal
self.signal_add(bt.SIGNAL_LONG, crossover) # use it as LONG signal
cerebro = bt.Cerebro() # create a "Cerebro" engine instance
feed = bt.feeds.PandasData(dataname=df)
cerebro.adddata(feed)# Add the data feed
cerebro.addstrategy(SmaCross) # Add the trading strategy
cerebro.run() # run it all
cerebro.plot() # and plot it with a single command