0

我正在尝试在 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



4

0 回答 0