Kwan Chi Yeung

Example in Tutorials (Moving Average)

Programming


There is only one instrument used In the moving average programming example. May I know if there is any method that can perform the same action but subscribes to more than one instrument? For example, is a for loop applicable to subscribe to more than one instrument, or do I have to add the same code for different instruments? javascript:nicTemp();



 
tony lam

Hi Kwan, on_bulkdatafeed would be more appropriate for your case. The 'bd' object in on_bulkdatafeed is a dictionary containing the latest price info for all your chosen instruments.

For the example in TechDoc, you can revise the data type for 'arr_close', 'arr_fastMA', and 'arr_slowMA' to dictionary. Then, you can loop all instruments and append the observations under on_bulkdatafeed later.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
from AlgoAPI import AlgoAPIUtil, AlgoAPI_Backtest
from datetime import datetime, timedelta
import talib, numpy

class AlgoEvent:
    def __init__(self):
        self.lasttradetime = datetime(2000,1,1)
        self.arr_close = {}
        self.arr_fastMA = {}
        self.arr_slowMA = {}
        self.fastperiod = 7
        self.slowperiod = 14

    def start(self, mEvt):
        self.instrument_1 = mEvt['subscribeList'][0]
        self.evt = AlgoAPI_Backtest.AlgoEvtHandler(self, mEvt)
        self.evt.start()

    def on_bulkdatafeed(self, isSync, bd, ab):
        if isSync and bd[self.instrument_1]['timestamp'] >= self.lasttradetime + timedelta(hours=24):
            self.lasttradetime = bd[self.instrument_1]['timestamp']

            for instrument in bd:
                
                # initialize array
                if instrument not in self.arr_close:
                    self.arr_close[instrument] = []
                    self.arr_fastMA[instrument] = []
                    self.arr_slowMA[instrument] = []


                lastprice = bd[instrument]['lastPrice']
                self.arr_close[instrument] = numpy.append(self.arr_close[instrument], lastprice)

                # keep the most recent observations
                if len(self.arr_close[instrument])>int(self.fastperiod+self.slowperiod):
                    self.arr_close[instrument] = self.arr_close[instrument][-int(self.fastperiod+self.slowperiod):]
                # fit SMA line
                self.arr_fastMA[instrument] = talib.SMA(self.arr_close[instrument], timeperiod=int(self.fastperiod))
                self.arr_slowMA[instrument] = talib.SMA(self.arr_close[instrument], timeperiod=int(self.slowperiod))
                # debug print result
                self.evt.consoleLog("arr_fastMA=", instrument, self.arr_fastMA[instrument])
                self.evt.consoleLog("arr_slowMA=", instrument, self.arr_slowMA[instrument])
                # check number of record is at least greater than both self.fastperiod, self.slowperiod
                if not numpy.isnan(self.arr_fastMA[instrument][-1]) and not numpy.isnan(self.arr_fastMA[instrument][-2]) and not numpy.isnan(self.arr_slowMA[instrument][-1]) and not numpy.isnan(self.arr_slowMA[instrument][-2]):
                    # send a buy order for Golden Cross
                    if self.arr_fastMA[instrument][-1] > self.arr_slowMA[instrument][-1] and self.arr_fastMA[instrument][-2] < self.arr_slowMA[instrument][-2]:
                        self.place_order(lastprice, 1, 'open', instrument)
                    # send a sell order for Death Cross
                    if self.arr_fastMA[instrument][-1] < self.arr_slowMA[instrument][-1] and self.arr_fastMA[instrument][-2] > self.arr_slowMA[instrument][-2]:
                        self.place_order(lastprice, -1, 'open', instrument)


    def place_order(self, lastprice, buysell, openclose, instrument):
        order = AlgoAPIUtil.OrderObject()
        order.instrument = instrument
        if buysell==1:
            order.takeProfitLevel = lastprice*1.1
            order.stopLossLevel = lastprice*0.9
        elif buysell==-1:
            order.takeProfitLevel = lastprice*0.9
            order.stopLossLevel = lastprice*1.1
        order.volume = 0.01
        order.openclose = openclose
        order.buysell = buysell
        order.ordertype = 0 #0=market_order, 1=limit_order
        self.evt.sendOrder(order)


 
Kwan Chi Yeung
Original Posted by - b'tony lam':

Hi Kwan, on_bulkdatafeed would be more appropriate for your case. The 'bd' object in on_bulkdatafeed is a dictionary containing the latest price info for all your chosen instruments.

For the example in TechDoc, you can revise the data type for 'arr_close', 'arr_fastMA', and 'arr_slowMA' to dictionary. Then, you can loop all instruments and append the observations under on_bulkdatafeed later.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
from AlgoAPI import AlgoAPIUtil, AlgoAPI_Backtest
from datetime import datetime, timedelta
import talib, numpy

class AlgoEvent:
    def __init__(self):
        self.lasttradetime = datetime(2000,1,1)
        self.arr_close = {}
        self.arr_fastMA = {}
        self.arr_slowMA = {}
        self.fastperiod = 7
        self.slowperiod = 14

    def start(self, mEvt):
        self.instrument_1 = mEvt['subscribeList'][0]
        self.evt = AlgoAPI_Backtest.AlgoEvtHandler(self, mEvt)
        self.evt.start()

    def on_bulkdatafeed(self, isSync, bd, ab):
        if isSync and bd[self.instrument_1]['timestamp'] >= self.lasttradetime + timedelta(hours=24):
            self.lasttradetime = bd[self.instrument_1]['timestamp']

            for instrument in bd:
                
                # initialize array
                if instrument not in self.arr_close:
                    self.arr_close[instrument] = []
                    self.arr_fastMA[instrument] = []
                    self.arr_slowMA[instrument] = []


                lastprice = bd[instrument]['lastPrice']
                self.arr_close[instrument] = numpy.append(self.arr_close[instrument], lastprice)

                # keep the most recent observations
                if len(self.arr_close[instrument])>int(self.fastperiod+self.slowperiod):
                    self.arr_close[instrument] = self.arr_close[instrument][-int(self.fastperiod+self.slowperiod):]
                # fit SMA line
                self.arr_fastMA[instrument] = talib.SMA(self.arr_close[instrument], timeperiod=int(self.fastperiod))
                self.arr_slowMA[instrument] = talib.SMA(self.arr_close[instrument], timeperiod=int(self.slowperiod))
                # debug print result
                self.evt.consoleLog("arr_fastMA=", instrument, self.arr_fastMA[instrument])
                self.evt.consoleLog("arr_slowMA=", instrument, self.arr_slowMA[instrument])
                # check number of record is at least greater than both self.fastperiod, self.slowperiod
                if not numpy.isnan(self.arr_fastMA[instrument][-1]) and not numpy.isnan(self.arr_fastMA[instrument][-2]) and not numpy.isnan(self.arr_slowMA[instrument][-1]) and not numpy.isnan(self.arr_slowMA[instrument][-2]):
                    # send a buy order for Golden Cross
                    if self.arr_fastMA[instrument][-1] > self.arr_slowMA[instrument][-1] and self.arr_fastMA[instrument][-2] < self.arr_slowMA[instrument][-2]:
                        self.place_order(lastprice, 1, 'open', instrument)
                    # send a sell order for Death Cross
                    if self.arr_fastMA[instrument][-1] < self.arr_slowMA[instrument][-1] and self.arr_fastMA[instrument][-2] > self.arr_slowMA[instrument][-2]:
                        self.place_order(lastprice, -1, 'open', instrument)


    def place_order(self, lastprice, buysell, openclose, instrument):
        order = AlgoAPIUtil.OrderObject()
        order.instrument = instrument
        if buysell==1:
            order.takeProfitLevel = lastprice*1.1
            order.stopLossLevel = lastprice*0.9
        elif buysell==-1:
            order.takeProfitLevel = lastprice*0.9
            order.stopLossLevel = lastprice*1.1
        order.volume = 0.01
        order.openclose = openclose
        order.buysell = buysell
        order.ordertype = 0 #0=market_order, 1=limit_order
        self.evt.sendOrder(order)


Hi Tony, thank you so much for your reply. I have followed the above code while developing my crypto trading strategy. However, my programme would not trade during the backtest even I just directly copy all functions above. May I know if I have missed any code in the "place_order" part? Additionally, is there a maximum value of the "order.volume". Thank you for your valuable time.
 
tony lam
Original Posted by - b'Kwan Chi Yeung': Hi Tony, thank you so much for your reply. I have followed the above code while developing my crypto trading strategy. However, my programme would not trade during the backtest even I just directly copy all functions above. May I know if I have missed any code in the "place_order" part? Additionally, is there a maximum value of the "order.volume". Thank you for your valuable time.
Hi Kwan, the logic above need to take the first 14-day observations to initialize the MA calculation. 
You can try with longer backtest period, and also different instruments. 

Secondly, the system doesn't have maximum restriction for order volume. 
However, an order will be rejected if there is insufficient balance. 
Those warning and error messages will be shown in "Console".