Path: blob/master/ invest-robot-contest_tinkoff_robot-master/tinkoff_robot.py
5925 views
import time1from tinkoff.invest import Client, MoneyValue, Quotation, OrderDirection, OrderType23figi_usd = "BBG0013HGFT4"4figi_Microsoft = "BBG000BPH459"5figi_Tesla = "BBG000N9MNX3"67# confidential information89token = ""10account_id = ""1112sandbox_token = token131415# function converts MoneyValue into float16def convert_price(MoneyValue):17price = MoneyValue.units + (MoneyValue.nano / 10**9)18return price192021# function converts float into MoneyValue22def convert_to_MoneyValue(price, currency='rub'):23units = price // 124nano = (price % 1) * 10**925return MoneyValue(units=units, nano=nano, currency=currency)262728# function gets info about current Limit Order Book29def get_LOB_data(figi_0=figi_usd):3031with Client(token) as client:32LOB = client.market_data.get_order_book(figi=figi_0, depth=50)3334ask_price = convert_price(LOB.asks[0].price)35bid_price = convert_price(LOB.bids[0].price)3637q_a = 038q_b = 03940for line in LOB.asks:41q_a += line.quantity42for line in LOB.bids:43q_b += line.quantity4445return ((q_b, q_a), (bid_price, ask_price))464748# function converts float into Quotation49def convert_to_Quotation(price, currency='rub'):50units = int(price // 1)51nano = int((price % 1) * 10**9)52return Quotation(units=units, nano=nano)535455# class consists of two models: last+im and last+im+v strategy56class model_1:57def __init__(self):58self.cur_best_bid_price = 059self.cur_best_ask_price = 06061self.last_best_bid_price = 062self.last_best_ask_price = 06364self.bid_quantity = 065self.ask_quantity = 06667self.ask_price = 068self.bid_price = 06970self.increment = 0.171self.auto_increment_flag = 172self.parameter = 0.5 #default parameter value73self.state = 07475self.colors = dict()76self.color_match = dict()7778self.colors["red"] = "\033[1;31m"79self.colors["green"] = "\033[1;32m"80self.colors["blue"] = "\033[1;34m"81self.colors["clear"] = "\033[0;0;m"8283self.color_match[0] = self.colors["blue"]84self.color_match[1] = self.colors["green"]85self.color_match[-1] = self.colors["red"]8687def set_parameters(self, param=0.5, increm=0):88self.parameter = param89if increm != 0:90self.auto_increment_flag = 091self.increment = increm9293def update_prices_b_a(self, bid_price, ask_price):9495self.last_best_bid_price = self.cur_best_bid_price96self.last_best_ask_price = self.cur_best_ask_price9798self.cur_best_bid_price = bid_price99self.cur_best_ask_price = ask_price100101if self.auto_increment_flag:102self.increment = ask_price - bid_price103104def update_LOB_data_b_a(self, b_q, a_q):105self.bid_quantity = b_q106self.ask_quantity = a_q107108def last_im_strategy(self):109value_1 = self.bid_quantity - self.ask_quantity110value_2 = -value_1111value_3 = self.ask_quantity + self.bid_quantity112113last_price = (self.cur_best_ask_price + self.cur_best_bid_price)/2114115if value_1/value_3 > self.parameter: #(qb -qs)/(qb +qs)>0.5116self.ask_price = last_price + self.increment * 2117self.bid_price = last_price118self.state = 1119120elif value_2/value_3 > self.parameter: #(qs –qb)/(qb +qs) >0.5121self.ask_price = last_price122self.bid_price = last_price - self.increment * 2123self.state = -1124125else:126self.ask_price = last_price + self.increment127self.bid_price = last_price - self.increment128self.state = 0129130print(self.color_match[self.state], end="")131print("last+im strategy")132print("signals: ----", end=' ')133print(self.bid_price, self.ask_price, sep=" : ", end='')134print(self.colors["clear"])135136return (self.bid_price, self.ask_price)137138def last_im_v_strategy(self):139value_1 = self.bid_quantity - self.ask_quantity140value_2 = -value_1141value_3 = self.ask_quantity + self.bid_quantity142143last_price = (self.cur_best_ask_price + self.cur_best_bid_price) / 2144previous_price = (self.last_best_ask_price + self.last_best_bid_price) / 2145146price_change = abs(last_price - previous_price)147148if value_1 / value_3 > self.parameter: # (qb -qs)/(qb +qs)>0.5149self.ask_price = last_price + (price_change + 2) * self.increment150self.bid_price = last_price - price_change * self.increment151self.state = 1152153154elif value_2 / value_3 > self.parameter: # (qs –qb)/(qb +qs) >0.5155self.ask_price = last_price + price_change * self.increment156self.bid_price = last_price - (price_change + 2) * self.increment157self.state = -1158159160else:161self.ask_price = last_price + (price_change + 1) * self.increment162self.bid_price = last_price - (price_change + 1) * self.increment163self.state = 0164165166print(self.color_match[self.state], end="")167print("last+im+v strategy")168print("signals: ----", end=' ')169print(self.bid_price, self.ask_price, sep=" : ", end='')170print(self.colors["clear"])171172173return (self.bid_price, self.ask_price)174175176# class simulates real time activity of the model, placing orders in the sandbox.177class SandboxTester:178def __init__(self, account_id, token, figi, model=model_1(), model_type="last_im_strategy", limit_quantity=10000000, limit_percentage=100, iterations=1000):179model_types = dict()180181model_types["last_im_strategy"] = 1182model_types["last_im_v_strategy"] = 2183184if model_types[model_type] is None:185raise Exception("Model type does not exist. Existing types: last_im_strategy, last_im_v_strategy")186else:187self.model_type = model_types[model_type]188189self.account_id = account_id190self.token = token191self.working_figi = figi192self.limit_quantity = limit_quantity193self.limit_percentage = limit_percentage194self.model = model195self.iterations = iterations196197from model_1_hft import get_LOB_data198199with Client(token=self.token) as client:200client_sb = client.sandbox201202self.moneeey = client_sb.get_sandbox_portfolio(account_id=self.account_id).total_amount_currencies203time.sleep(0.6)204205self.money_float = convert_price(self.moneeey)206max_quantity = convert_price(self.moneeey)207last_price = client.market_data.get_last_prices(figi=[self.working_figi]).last_prices[0].price208time.sleep(0.6)209210self.last_price = convert_price(last_price)211self.max_quantity = max_quantity // self.last_price212213self.cur_balance = self.money_float214215def model_run(self):216if self.model_type == 1:217return self.model.last_im_strategy()218elif self.model_type == 2:219return self.model.last_im_v_strategy()220else:221return None222223def update_balance(self):224with Client(token=self.token) as client:225client_sb = client.sandbox226self.cur_balance = client_sb.get_sandbox_portfolio(account_id=self.account_id).total_amount_currencies227self.cur_balance = convert_price(self.cur_balance)228print(self.cur_balance)229print("////////")230time.sleep(0.6)231# print(client_sb.get_sandbox_portfolio(account_id=self.account_id))232233def place_order_ask(self, price, quantity, time_c=0):234if time_c > 3:235return "ASK order was NOT EXECUTED"236237try:238with Client(token=self.token) as client:239r = client.sandbox.post_sandbox_order(240figi=self.working_figi,241price=price,242x_app_name="naketu.HFT",243quantity=quantity,244account_id=self.account_id,245order_id="sfkjhsf234897kjsdfh8has8dy3827gdslu[]" + str(time.localtime()),246direction=OrderDirection.ORDER_DIRECTION_SELL,247order_type=OrderType.ORDER_TYPE_LIMIT248)249250time.sleep(0.6)251return r252253except:254time.sleep(0.6)255time_c += 0.6256257print("ERROR OCCURED AT ASK POST ORDER, reposting...")258259r = self.place_order_bid(price, quantity, time_c)260return r261262def place_order_bid(self, price, quantity, time_c=0):263if time_c > 3:264return "BID order was NOT EXECUTED"265266try:267with Client(token=self.token) as client:268269r = client.sandbox.post_sandbox_order(270figi=self.working_figi,271price=price,272#appname="naketu.HFT",273quantity=quantity,274account_id=self.account_id,275order_id="sfkjhsf234897kjsdfh8has8dy3827gdslu[]" + str(time.localtime()),276direction=OrderDirection.ORDER_DIRECTION_BUY,277order_type=OrderType.ORDER_TYPE_LIMIT278)279280time.sleep(0.6)281return r282283except:284time.sleep(0.6)285time_c += 0.6286287print("ERROR OCCURED AT BID POST ORDER, reposting...")288289r = self.place_order_bid(price, quantity, time_c)290return r291292def cancel_order(self, order_id):293with Client(token=self.token) as client:294try:295r = client.sandbox.cancel_sandbox_order(296account_id=self.account_id,297order_id=order_id,298)299time.sleep(0.6)300except:301r = "ORDER IS NOT CANCELED"302return r303304def check_orders(self, last_bid_price, bid_price, last_ask_price, ask_price):305with Client(token=self.token) as client:306orders = client.sandbox.get_sandbox_orders(account_id=self.account_id)307time.sleep(0.6)308309if last_bid_price != bid_price and last_ask_price != ask_price:310return orders.orders311elif last_bid_price != bid_price:312orders = [ord for ord in orders.orders if ord.direction == OrderDirection.ORDER_DIRECTION_BUY]313return orders314elif last_ask_price != ask_price:315orders = [ord for ord in orders.orders if ord.direction == OrderDirection.ORDER_DIRECTION_SELL]316return orders317else:318return []319320def test(self):321time_c = 0322323last_bid_price = 0324last_ask_price = 0325326try:327old_LOB = get_LOB_data(self.working_figi)328time.sleep(0.6)329except:330raise Exception("NO CONNECTION TO MARKET")331332for i in range(self.iterations):333334self.update_balance()335336try:337LOB_data = get_LOB_data(self.working_figi)338except:339print("LOB does not responding")340time.sleep(2)341time_c += 2342print("loading...", time_c)343continue344345if old_LOB[0][0] == LOB_data[0][0] and old_LOB[0][1] == LOB_data[0][1]:346continue347else:348self.model.update_LOB_data_b_a(LOB_data[0][0], LOB_data[0][1])349self.model.update_prices_b_a(LOB_data[1][0], LOB_data[1][1])350351cur_price = (LOB_data[1][0] + LOB_data[1][1])/2352353response = self.model_run()354355bid_price = convert_to_Quotation(response[0])356ask_price = convert_to_Quotation(response[1])357358orders = self.check_orders(last_bid_price, bid_price, last_ask_price, ask_price)359360if len(orders) != 0:361for order in orders:362self.cancel_order(order.order_id)363364quantity = int(min(self.limit_percentage/100 * self.money_float,365self.limit_quantity, self.cur_balance // cur_price))366367self.place_order_ask(ask_price, quantity // 2),368self.place_order_bid(bid_price, quantity // 2)369370# print(self.place_order_ask(ask_price, quantity // 2),371# self.place_order_bid(bid_price, quantity // 2))372373last_bid_price = bid_price374last_ask_price = ask_price375376time.sleep(0.6)377378379"""380The function simulates trading session and outputs order prices that are given out by the strategies states in model_1.381However, the function does not post any orders. Colored lines represent the results of the algorithm,382where blue, red and green represent steady state of the order book, greater amount of ask and bid orders respectively.383"""384def algo_trade(figi="BBG0013HGFT4"):385386BEST_MODEL_EVER = model_1()387388working_figi = figi389390try: old_LOB = get_LOB_data(working_figi)391except:392print("WARNING")393print()394395time_c = 0396397print("start")398399for i in range(1000):400401try: LOB_data = get_LOB_data(working_figi)402except:403print("i am dead")404print("Too many calls ERROR")405time.sleep(2)406time_c += 2407print("loading...", time_c)408continue409410if (old_LOB == None) or (old_LOB[0][0] == LOB_data[0][0] and old_LOB[0][1] == LOB_data[0][1]):411time.sleep(0.6)412time_c += 0.6413print("loading...", time_c)414415else:416time_c = 0417print("///////////////////////////")418419print("quantity: ---", LOB_data[0][0], LOB_data[0][1])420print("prices: -----", LOB_data[1][0], LOB_data[1][1])421422BEST_MODEL_EVER.update_LOB_data_b_a(LOB_data[0][0], LOB_data[0][1])423BEST_MODEL_EVER.update_prices_b_a(LOB_data[1][0], LOB_data[1][1])424425response1 = BEST_MODEL_EVER.last_im_strategy()426response2 = BEST_MODEL_EVER.last_im_v_strategy()427428print("///////////////////////////")429430time.sleep(0.6)431time_c += 0.6432433old_LOB = LOB_data434435436def sandbox_quick_start(figi=figi_usd):437model_1_test = model_1()438tester_0 = SandboxTester(account_id, token, figi, model_1_test, "last_im_strategy", 1000, 10, 10000)439tester_0.test()440441442def pay_in():443with Client(token=token) as client:444client_sb = client.sandbox445client_sb.sandbox_pay_in(account_id=account_id, amount=MoneyValue(units=100000, nano=0, currency='rub'))446447448"""QUICK START:449Comment out one of the functions below and input initial values for token and account_id at the beginning of the file450If current trading balance is zero, you can add 100000 rub there by initiating pay_in() function """451452453# algo_trade(figi_Tesla)454# sandbox_quick_start(figi_Tesla)455456457