-
Notifications
You must be signed in to change notification settings - Fork 118
/
strat_dual_thrust.py
133 lines (124 loc) · 6.33 KB
/
strat_dual_thrust.py
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#-*- coding:utf-8 -*-
#from base import *
from misc import *
from strategy import *
class DTTrader(Strategy):
def __init__(self, name, underliers, volumes, agent = None, trade_unit = [], ratios = [], lookbacks=[], daily_close = False, email_notify = None, ma_win = 10, min_rng = [0.00]):
Strategy.__init__(self, name, underliers, volumes, trade_unit, agent, email_notify)
self.lookbacks = lookbacks
numAssets = len(underliers)
self.ratios = [[0.5, 0.5]] * numAssets
if len(ratios) > 1:
self.ratios = ratios
elif len(ratios) == 1:
self.ratios = ratios * numAssets
if len(lookbacks) > 0:
self.lookbacks = lookbacks
else:
self.lookbacks = [0] * numAssets
self.cur_rng = [0.0] * numAssets
self.cur_ma = [0.0] * numAssets
self.tday_open = [0.0] * numAssets
self.tick_base = [0.0] * numAssets
self.order_type = OPT_LIMIT_ORDER
self.daily_close_buffer = 3
self.close_tday = [False] * numAssets
if len(daily_close) > 1:
self.close_tday = daily_close
elif len(daily_close) == 1:
self.close_tday = daily_close * numAssets
self.ma_win = ma_win
self.num_tick = 1
self.min_rng = [0.0] * numAssets
if len(min_rng) > 1:
self.min_rng = min_rng
elif len(min_rng) == 1:
self.min_rng = min_rng * numAssets
def initialize(self):
self.load_state()
for idx, underlier in enumerate(self.underliers):
inst = underlier[0]
self.tick_base[idx] = self.agent.instruments[inst].tick_base
ddf = self.agent.day_data[inst]
win = self.lookbacks[idx]
if win > 0:
self.cur_rng[idx] = max(max(ddf.ix[-win:,'high'])- min(ddf.ix[-win:,'close']), max(ddf.ix[-win:,'close']) - min(ddf.ix[-win:,'low']))
elif win == 0:
self.cur_rng[idx] = max(max(ddf.ix[-2:,'high'])- min(ddf.ix[-2:,'close']), max(ddf.ix[-2:,'close']) - min(ddf.ix[-2:,'low']))
self.cur_rng[idx] = max(self.cur_rng[idx] * 0.5, ddf.ix[-1,'high']-ddf.ix[-1,'close'],ddf.ix[-1,'close']-ddf.ix[-1,'low'])
else:
self.cur_rng[idx] = max(ddf.ix[-1,'high']- ddf.ix[-1,'low'], abs(ddf.ix[-1,'close'] - ddf.ix[-2,'close']))
self.cur_ma[idx] = ddf.ix[-self.ma_win:, 'close'].mean()
min_id = self.agent.instruments[inst].last_tick_id/1000
min_id = int(min_id/100)*60 + min_id % 100 - self.daily_close_buffer
self.last_min_id[idx] = int(min_id/60)*100 + min_id % 60
self.save_state()
return
def save_local_variables(self, file_writer):
for idx, underlier in enumerate(self.underliers):
inst = underlier[0]
row = ['CurrRange', str(inst), self.cur_rng[idx]]
file_writer.writerow(row)
return
def load_local_variables(self, row):
if row[0] == 'CurrRange':
inst = str(row[1])
idx = self.under2idx[inst]
if idx >= 0:
self.cur_rng[idx] = float(row[2])
return
def on_tick(self, idx, ctick):
if len(self.submitted_trades[idx]) > 0:
return
inst = self.underliers[idx][0]
self.tday_open[idx] = self.agent.cur_day[inst]['open']
if (self.tday_open[idx] <= 0.0) or (self.cur_rng[idx] <= 0) or (self.curr_prices[idx] <= 0.001):
self.logger.warning("warning: open price =0.0 or range = 0.0 or curr_price=0 for inst=%s for stat = %s" % (inst, self.name))
return
min_id = self.agent.tick_id/1000.0
num_pos = len(self.positions[idx])
buysell = 0
if num_pos > 1:
self.logger.warning('something wrong with position management - submitted trade is empty but trade position is more than 1')
return
elif num_pos == 1:
buysell = self.positions[idx][0].direction
tick_base = self.tick_base[idx]
t_open = self.tday_open[idx]
c_rng = max(self.cur_rng[idx] * self.ratios[idx][0], t_open * self.min_rng[idx])
buy_trig = t_open + c_rng
sell_trig = t_open - c_rng
if self.cur_ma[idx] > t_open:
buy_trig += self.ratios[idx][1] * c_rng
elif self.cur_ma[idx] < t_open:
sell_trig -= self.ratios[idx][1] * c_rng
buy_trig = min(self.agent.instruments[inst].up_limit - 5*tick_base, buy_trig)
sell_trig = max(self.agent.instruments[inst].down_limit + 5*tick_base, sell_trig)
if (min_id >= self.last_min_id[idx]):
if (buysell!=0) and (self.close_tday[idx]):
msg = 'DT to close position before EOD for inst = %s, direction=%s, volume=%s, current tick_id = %s' \
% (inst, buysell, self.trade_unit[idx], min_id)
self.close_tradepos(idx, self.positions[idx][0], self.curr_prices[idx] - buysell * self.num_tick * tick_base)
self.status_notifier(msg)
self.save_state()
return
if ((self.curr_prices[idx] >= buy_trig) and (buysell <=0)) or ((self.curr_prices[idx] <= sell_trig) and (buysell >=0)):
if buysell!=0:
msg = 'DT to close position for inst = %s, open= %s, buy_trig=%s, sell_trig=%s, curr_price= %s, direction=%s, volume=%s' \
% (inst, self.tday_open[idx], buy_trig, sell_trig, self.curr_prices[idx], buysell, self.trade_unit[idx])
self.close_tradepos(idx, self.positions[idx][0], self.curr_prices[idx] - buysell * self.num_tick * tick_base)
self.status_notifier(msg)
if self.trade_unit[idx] <= 0:
return
if (self.curr_prices[idx] >= buy_trig):
buysell = 1
else:
buysell = -1
msg = 'DT to open position for inst = %s, open= %s, buy_trig=%s, sell_trig=%s, curr_price= %s, direction=%s, volume=%s' \
% (inst, self.tday_open[idx], buy_trig, sell_trig, self.curr_prices[idx], buysell, self.trade_unit[idx])
self.open_tradepos(idx, buysell, self.curr_prices[idx] + buysell * self.num_tick * tick_base)
self.status_notifier(msg)
self.save_state()
return
def update_trade_unit(self):
pass