Dave-Vallance / bt-ccxt-store

Fork of Ed Bartosh's CCXT Store Work
MIT License
423 stars 187 forks source link

more than one datafeed #26

Closed planet-winter closed 4 years ago

planet-winter commented 4 years ago

Hi,

I have tried to get a strategy with 2 data feeds working. eg. hourly and daily. However even after both feeds have live data the strategy next() function is not called.

Is this a bug or does anyone know how to achieve it?

Dave-Vallance commented 4 years ago

Can you provide a full working example of the issue you are having? Hard to say where the problem is with a short description.

planet-winter commented 4 years ago

Hi @Dave-Vallance

Thank you for your response. I realized it is pretty straight forward while assembling below working example.

#!/usr/bin/env python3

import backtrader as bt
import datetime as dt
import sys
from ccxtbt import CCXTStore
import time

DEBUG = False
# https://docs.bitfinex.com/reference#rest-auth-new-order
# https://docs.bitfinex.com/reference#rest-auth-order-status
BITFINEX = {
    "broker_config": {
        'apiKey': "xxx",
        'secret': "xxx",
        'nonce': lambda: str(int(time.time() * 1000)),
        'enableRateLimit': True,
        'rateLimit': 15000  # 4 times per minute or less should work
    },
    "broker_mapping": {
        "order_types":
         {
             bt.Order.Market: 'exchange market',
             bt.Order.Limit: 'exchange limit',
             bt.Order.Stop: 'exchange stop',
             bt.Order.StopLimit: 'exchange stop-limit'
        },
        "mappings": {
                    'closed_order':{
                        'key': 'status',
                        'value':'closed'
                        },
                    'canceled_order':{
                        'key': 'is_cancelled',
                        'value': True
                        }
        }
    }
}

class Strategy(bt.Strategy):

    def __init__(self):
        if len(self.datas) < 2:
            print("Not enough datas %s" % len(self.datas))
        self.order = None
        self.live_data = False

    def notify_data(self, data, status, *args, **kwargs):
        dn = data._name
        t = dt.datetime.now()
        print('{} - {} - Data Status: {}'.format(t, dn, data._getstatusname(status)))
        if data._getstatusname(status) == 'LIVE':
            self.live_data = True
        else:
            self.live_data = False

    def next(self):
        print("strategy next() reached")

        if not self.live_data:
             print("No live data yet in strategy next")
             return

        print("1BTC@%s" % (self.data0[0]))

        if not self.position:
            print("NOP")
        elif self.position:
            print("NOP")

def main():
    cerebro = bt.Cerebro(quicknotify=True, cheat_on_open=True, runonce=False)

    broker_config = BITFINEX.get("broker_config")

   store0 = CCXTStore(
        exchange='bitfinex',
        currency='USD',
        config=broker_config,
        retries=10,
        debug=DEBUG,
    )

    broker_mapping = BITFINEX.get("broker_mapping")

    broker = store0.getbroker(broker_mapping=broker_mapping)
    cerebro.setbroker(broker)

    hist_start_date = dt.datetime.utcnow() - dt.timedelta(minutes=30)

     data0 = store0.getdata(
        dataname='%s/%s' % ('BTC', 'USD'),
        name='%s%s@%s' % ('BTC', 'USD', '1m'),
        timeframe=bt.TimeFrame.Minutes,
        fromdate=hist_start_date,
        compression=1,
        ohlcv_limit=150,
        debug=DEBUG,
        #backfill_start=True
    )

    data1 = store0.getdata(
        dataname='%s/%s' % ('BTC', 'USD'),
        name='%s%s@%s' % ('BTC', 'USD', '5m'),
        timeframe=bt.TimeFrame.Minutes,
        fromdate=hist_start_date,
        compression=5,
        ohlcv_limit=30,
        debug=DEBUG,
        #backfill_start=True
    )

    cerebro.adddata(data0)
    cerebro.adddata(data1)

    cerebro.addstrategy(Strategy)
    #cerebro.addsizer(CryptoSizer, prop=0.01)

    # run it
    result = cerebro.run()

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        time = dt.datetime.now().strftime("%d-%m-%y %H:%M")
        print("Bot finished by user at %s" % time)
    except Exception as err:
        print("Bot finished with error: %s" % err)
        raise

With output: 2020-05-12 10:09:04.470426 - BTCUSD@1m - Data Status: DELAYED 2020-05-12 10:09:04.470648 - BTCUSD@5m - Data Status: DELAYED strategy next() reached No live data yet in strategy next strategy next() reached No live data yet in strategy next ... strategy next() reached No live data yet in strategy next 2020-05-12 10:09:34.690395 - BTCUSD@5m - Data Status: LIVE strategy next() reached 1BTC@8657.3 NOP

Note: only the 5m data feed is reported to be live

The not working Strategy I tried earlier started running yesterday with live data after a few days delay. It is on higher time frames. I assume it might have been due to _fromdate not being aligned with needed period and _ohlcvlimit.

Thank you for your work on bt-ccxt-store and sorry for the noise