Skip to content

Commit ba33f7d

Browse files
romanpbmrok-povsic
authored andcommitted
Add sample trading strategy
1 parent 7116e4b commit ba33f7d

1 file changed

Lines changed: 133 additions & 0 deletions

File tree

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import pyl1api as bm
2+
3+
alias_to_order_book = {}
4+
alias_to_instrument = {}
5+
alias_to_buy_order_id = {}
6+
alias_to_sell_order_id = {}
7+
alias_to_position = {}
8+
req_id = 0
9+
interval_count = 0
10+
INITIAL_THRESHOLD = 10 # relative value, multiply it by size_multiplier to get actual value
11+
INITIAL_ORDER_SIZE = 1 # same as INITIAL_THRESHOLD
12+
INITIAL_SHIFT = 60 # absolute value, pips doesn't apply here
13+
14+
15+
def handle_instrument_info(addon, alias, full_name, is_crypto, pips, size_multiplier, instrument_multiplier):
16+
global req_id
17+
18+
instrument = {
19+
"alias": alias,
20+
"full_name": full_name,
21+
"is_crypto": is_crypto,
22+
"pips": pips,
23+
"size_multiplier": size_multiplier,
24+
"instrument_multiplier": instrument_multiplier
25+
}
26+
alias_to_instrument[alias] = instrument
27+
alias_to_order_book[alias] = bm.create_order_book()
28+
req_id += 1
29+
bm.subscribe_to_depth(addon, alias, req_id)
30+
req_id += 1
31+
bm.subscribe_to_order_info(addon, alias, req_id)
32+
req_id += 1
33+
bm.subscribe_to_position_updates(addon, alias, req_id)
34+
print("Registered...", flush=True)
35+
36+
37+
def handle_instrument_detached(addon, alias):
38+
del alias_to_order_book[alias]
39+
del alias_to_instrument[alias]
40+
41+
42+
def handle_depth_info(addon, alias, is_bid, price, size):
43+
order_book = alias_to_order_book[alias]
44+
bm.on_depth(order_book, is_bid, price, size)
45+
46+
47+
def order_update_handler(addon, event):
48+
status = event['status']
49+
if (status == 'WORKING'):
50+
if (event['isBuy'] == True):
51+
alias_to_buy_order_id[event['instrumentAlias']] = event['orderId']
52+
print("current buys " + str(alias_to_buy_order_id), flush=True)
53+
else:
54+
alias_to_sell_order_id[event['instrumentAlias']] = event['orderId']
55+
print("current sells " + str(alias_to_sell_order_id), flush=True)
56+
elif (status == 'CANCELLED'):
57+
if (event['isBuy'] == True):
58+
if (event['instrumentAlias'] in alias_to_buy_order_id):
59+
del alias_to_buy_order_id[event['instrumentAlias']]
60+
print("current buys " + str(alias_to_buy_order_id), flush=True)
61+
else:
62+
if (event['instrumentAlias'] in alias_to_sell_order_id):
63+
del alias_to_sell_order_id[event['instrumentAlias']]
64+
print("current sells " + str(alias_to_sell_order_id), flush=True)
65+
print("Order Update: " + str(event), flush=True)
66+
67+
68+
def position_update_handler(addon, event):
69+
# here we receive postion size as integer value, with instruments
70+
# that may be decimal fractions apply size_multiplier to get actual position size
71+
alias_to_position[event['instrumentAlias']] = event['position']
72+
print("Position Update: " + str(event), flush=True)
73+
74+
75+
def order_execute_handler(addon, alias, event):
76+
if (event['orderId'] in alias_to_buy_order_id.values()):
77+
del alias_to_buy_order_id[alias]
78+
print("current buys after execution " + str(alias_to_buy_order_id), flush=True)
79+
elif (event['orderId'] in alias_to_sell_order_id.values()):
80+
del alias_to_sell_order_id[alias]
81+
print("current sells after execution " + str(alias_to_sell_order_id), flush=True)
82+
print("Order execute alias: " + alias + " entity: " + str(event), flush=True)
83+
84+
85+
# callback triggered with periodic interval, right not it is not configurable and used
86+
def on_interval(addon):
87+
global interval_count
88+
interval_count += 1
89+
# interval is 0.1 sec, if we want to process orders once per 3 seconds then every 30 on_interval calls
90+
# we will perform trading related activity
91+
if interval_count % 30 == 0:
92+
print("3 secs passed", flush=True)
93+
94+
for alias, order_book in alias_to_order_book.items():
95+
if alias in alias_to_instrument:
96+
(best_bid_price_level, best_bid_size_level), (best_ask_price_level, best_ask_size_level) = bm.get_bbo(order_book)
97+
instrument = alias_to_instrument[alias]
98+
instrument_pips = instrument["pips"]
99+
print("pips = " + str(instrument_pips), flush=True)
100+
# note: alias_to_position[alias] is not actual postion size, actual postion size = alias_to_position[alias] * size_multiplier
101+
position = 0
102+
if (alias in alias_to_position):
103+
position = alias_to_position[alias]
104+
# note: position is not actual postion size, actual postion size = position * size_multiplier
105+
if (position < INITIAL_THRESHOLD):
106+
if (alias in alias_to_buy_order_id):
107+
print("attempt to move buy order with price" + str(best_bid_price_level * instrument_pips - INITIAL_SHIFT), flush=True)
108+
bm.move_order(addon, alias, alias_to_buy_order_id[alias], best_bid_price_level * instrument_pips - INITIAL_SHIFT)
109+
else:
110+
print("attempt to send buy order with price" + str(best_bid_price_level * instrument_pips - INITIAL_SHIFT), flush=True)
111+
# note: INITIAL_ORDER_SIZE is not actual order size, actual order size = INITIAL_ORDER_SIZE * size_multiplier
112+
bm.send_order(addon, alias, True, INITIAL_ORDER_SIZE, 'GTC', best_bid_price_level * instrument_pips - INITIAL_SHIFT)
113+
114+
# note: position is not actual postion size, actual postion size = position * size_multiplier
115+
if (position > -INITIAL_THRESHOLD):
116+
if (alias in alias_to_sell_order_id):
117+
print("attempt to move sell order with price" + str(best_ask_price_level * instrument_pips + INITIAL_SHIFT), flush=True)
118+
bm.move_order(addon, alias, alias_to_sell_order_id[alias], best_ask_price_level * instrument_pips + INITIAL_SHIFT)
119+
else:
120+
print("attempt to send sell order with price" + str(best_ask_price_level * instrument_pips + INITIAL_SHIFT), flush=True)
121+
# note: INITIAL_ORDER_SIZE is not actual order size, actual order size = INITIAL_ORDER_SIZE * size_multiplier
122+
bm.send_order(addon, alias, False, INITIAL_ORDER_SIZE, 'GTC', best_ask_price_level * instrument_pips + INITIAL_SHIFT)
123+
124+
125+
if __name__ == "__main__":
126+
addon = bm.create_addon()
127+
bm.add_depth_handler(addon, handle_depth_info)
128+
bm.add_on_interval_handler(addon, on_interval)
129+
bm.add_on_order_executed_handler(addon, order_execute_handler)
130+
bm.add_on_order_updated_handler(addon, order_update_handler)
131+
bm.add_on_position_update_handler(addon, position_update_handler)
132+
bm.start_addon(addon, handle_instrument_info, handle_instrument_detached)
133+
bm.wait_until_addon_is_turned_off(addon)

0 commit comments

Comments
 (0)