def test_invalid_trade(self): buy = createBuy() # Orders shouldn't should only fill to opposing side assert not Trade.create(buy, buy) # Order shouldn't match if the prices don't intersect assert not Trade.create(buy, createSell(price=101))
def create(self): """Create a trade from the instance created by the constructor""" Trade.create( user_one=self.user_one, user_two=self.user_two, book_one=self.book_one, book_two=self.book_two, status=self.status )
def create_trade(user_one=None, user_two=None, book_one=None, book_two=None, status="processing"): """Static method to create trade.""" Trade.create( user_one=user_one, user_two=user_two, book_one=book_one, book_two=book_two, status=status )
def test_partially_filled(self): # Same size orders should fill each other completely buy = createBuy(quantity=200) sell = createSell() trade = Trade.create(buy, sell) assert trade assert trade.quantity == sell.quantity assert buy.unfilled() == 100 assert sell.unfilled() == 0 sell = createSell(quantity=300) trade = Trade.create(buy, sell) assert trade assert trade.quantity == 100 assert buy.unfilled() == 0 assert sell.unfilled() == 200
def sell(currency): symbol = '{}{}'.format(currency, CURRENCY) balance = get_balance(currency) quantity = get_quantity(currency) if quantity > 0: info = client.get_symbol_info(symbol=symbol) stepSize = float(info['filters'][2]['stepSize']) precision = int(round(-math.log(stepSize, 10), 0)) if quantity >= balance: quantity = balance order = client.create_order(symbol=symbol, side=Client.SIDE_SELL, type=Client.ORDER_TYPE_MARKET, quantity=round_down(quantity, precision)) print(order) quantity = 0 fee = 0 for fill in order['fills']: fee += float(fill['commission']) quantity += float(fill['qty']) price = float(order['fills'][0]['price']) total = float(order['cummulativeQuoteQty']) total = total - fee now = datetime.now() Trade.create(currency=currency, quantity=quantity, price=price, fee=fee, total=total, type='sell', date=now, epoch=now.timestamp(), test=False) if TELEGRAM_TOKEN and TELEGRAM_PRIVATE_CHAT_ID: send_private_telegram('{} {} SOLD FOR {}{}'.format( quantity, currency, round(total, 2), CURRENCY))
def on_trade(self, msg): if not self.is_ready: self.process_later.append(msg) return trade = { "price": msg.get('MDEntryPx'), "symbol": msg.get('Symbol'), "size": msg.get('MDEntrySize'), "trade_date": msg.get('MDEntryDate'), "trade_time": msg.get('MDEntryTime'), "order_id": msg.get('OrderID'), "side": msg.get('Side'), "counter_order_id": msg.get('SecondaryOrderID'), "id": msg.get('TradeID'), "buyer_id": msg.get('MDEntryBuyerID'), "seller_id": msg.get('MDEntrySellerID'), "buyer_username": msg.get('MDEntryBuyer'), "seller_username": msg.get('MDEntrySeller'), } Trade.create(self.db_session, trade) # BTC BRL price_currency = self.symbol[3:] size_currency = self.symbol[:3] if price_currency not in self.volume_dict: self.volume_dict[price_currency] = 0 if size_currency not in self.volume_dict: self.volume_dict[size_currency] = 0 volume_price = int( msg.get('MDEntryPx') * msg.get('MDEntrySize') / 1.e8) volume_size = msg.get('MDEntrySize') self.volume_dict[price_currency] += volume_price self.volume_dict[size_currency] += volume_size self.volume_dict['MDEntryType'] = '4' signal_publish_md_status('MD_STATUS', self.volume_dict) self.inst_status.push_trade(trade)
def buy(currency, input=ORDER_INPUT): symbol = '{}{}'.format(currency, CURRENCY) order_price = float(input) trades = client.get_recent_trades(symbol=symbol) price = float(trades[0]['price']) quantity = order_price / price info = client.get_symbol_info(symbol=symbol) stepSize = float(info['filters'][2]['stepSize']) precision = int(round(-math.log(stepSize, 10), 0)) order = client.create_order(symbol=symbol, side=Client.SIDE_BUY, type=Client.ORDER_TYPE_MARKET, quantity=(round(quantity, precision))) print(order) quantity = 0 commission = 0 for fill in order['fills']: commission += float(fill['commission']) quantity += float(fill['qty']) quantity = quantity - commission price = float(order['fills'][0]['price']) total = float(order['cummulativeQuoteQty']) fee = commission * price now = datetime.now() Trade.create(currency=currency, quantity=quantity, price=price, fee=fee, total=total, type='buy', date=now, epoch=now.timestamp(), test=False) if TELEGRAM_TOKEN and TELEGRAM_PRIVATE_CHAT_ID: send_private_telegram('{} {} BOUGHT FOR {}{}'.format( quantity, currency, round(total, 2), CURRENCY))
def test_sell(symbol, ticker): quantity = get_currency_wallet_value(symbol, test=True) if quantity > 0: print('{}: SELLING {}{} at {}{} => {}{}'.format( ticker.datetime, quantity, symbol, ticker.price, CURRENCY, (quantity * ticker.price), CURRENCY)) price = ticker.price sale = price * quantity fee = (sale / 100) * 0.1 total = sale - fee Trade.create(currency=symbol, quantity=quantity, price=ticker.price, fee=fee, total=total, type='sell', date=ticker.datetime, epoch=ticker.epoch, test=True)
def test_buy(symbol, ticker): order_price = float(ORDER_INPUT) price = float(ticker.price) quantity = order_price / price print('{}: BUYING {}{} at {}{} => {}{}'.format(ticker.datetime, quantity, symbol, price, CURRENCY, (quantity * price), CURRENCY)) # TODO: Fix correct calculations fee_currency = (quantity / 100) * 0.1 quantity = quantity - fee_currency fee = fee_currency * price total = order_price + fee Trade.create(currency=symbol, quantity=quantity, price=price, fee=fee, total=total, type='buy', date=ticker.datetime, epoch=ticker.epoch, test=True)
def exit_entire_trade(self): quantity_to_sell = 0 total_return = 0 for entry in self.current_entries: if "exit" not in self.current_entries[entry]: quantity_to_sell += self.current_entries[entry]['entry'][ 'quantity'] self.current_entries[entry]['exit'] = { "price": self.bid, "quantity": self.current_entries[entry]['entry']['quantity'], "dt": datetime.datetime.now() } entry_price = self.current_entries[entry]['entry']['price'] exit_price = self.current_entries[entry]['exit']['price'] trade = Trade.create( bot_name=self.name, quantity=self.current_entries[entry]['entry']['quantity'], first_trade_time=self.current_entries[0]['entry']['dt'], entry_time=self.current_entries[entry]['entry']['dt'], exit_time=self.current_entries[entry]['exit']['dt'], entry_price=self.current_entries[entry]['entry']['price'], exit_price=self.current_entries[entry]['exit']['price'], target_entry=self.lower_resistance_level, target_exit=self.upper_resistance_level, entry_level=entry, ) total_return += (exit_price / entry_price - 1) dollar_return = quantity_to_sell * (total_return - 0.0015) self.twilio.message( "Entered @ {}\nExited @ {}\nAverage Return {}\nTotal Return {}". format(self.current_entries[0]['entry']['price'], self.bid, (total_return / len(self.current_entries)), dollar_return)) self.current_entries = {} self.last_order = self.binance_api.market_sell(self.pair, quantity_to_sell) self.locked_resistance_levels = False
def __init__(self, opt, instance_name): self.options = opt self.instance_name = instance_name handlers = [ (r'/', WebSocketHandler), (r'/get_deposit(.*)', DepositHandler), (r'/_webhook/verification_form', VerificationWebHookHandler), (r'/_webhook/deposit_receipt', DepositReceiptWebHookHandler), (r'/process_deposit(.*)', ProcessDepositHandler), (r'/api/(?P<version>[^\/]+)/(?P<symbol>[^\/]+)/(?P<resource>[^\/]+)', RestApiHandler) ] settings = dict(cookie_secret='cookie_secret') tornado.web.Application.__init__(self, handlers, **settings) self.allowed_origins = json.loads(self.options.allowed_origins) self.allow_all_origins = self.allowed_origins[0] == '*' input_log_file_handler = logging.handlers.TimedRotatingFileHandler( os.path.expanduser(self.options.gateway_log), when='MIDNIGHT') formatter = logging.Formatter('%(asctime)s - %(message)s') input_log_file_handler.setFormatter(formatter) self.replay_logger = logging.getLogger(self.instance_name) self.replay_logger.setLevel(logging.INFO) self.replay_logger.addHandler(input_log_file_handler) ch = logging.StreamHandler(sys.stdout) ch.setLevel(logging.DEBUG) ch.setFormatter( logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s')) self.replay_logger.addHandler(ch) self.replay_logger.info('START') self.log_start_data() self.update_tor_nodes() from models import Base, db_bootstrap db_engine = self.options.sqlalchemy_engine + ':///' +\ os.path.expanduser(self.options.sqlalchemy_connection_string) engine = create_engine(db_engine, echo=self.options.db_echo) Base.metadata.create_all(engine) self.db_session = scoped_session(sessionmaker(bind=engine)) db_bootstrap(self.db_session) self.zmq_context = zmq.Context() self.trade_in_socket = self.zmq_context.socket(zmq.REQ) self.trade_in_socket.connect(self.options.trade_in) self.application_trade_client = TradeClient(self.zmq_context, self.trade_in_socket) self.application_trade_client.connect() self.security_list = self.application_trade_client.getSecurityList() self.md_subscriber = {} for instrument in self.security_list.get('Instruments'): symbol = instrument['Symbol'] self.md_subscriber[symbol] = MarketDataSubscriber.get(symbol, self) self.md_subscriber[symbol].subscribe(self.zmq_context, self.options.trade_pub, self.application_trade_client) last_trade_id = Trade.get_last_trade_id(self.db_session) trade_list = self.application_trade_client.getLastTrades(last_trade_id) for trade in trade_list: msg = dict() msg['id'] = trade[0] msg['symbol'] = trade[1] msg['side'] = trade[2] msg['price'] = trade[3] msg['size'] = trade[4] msg['buyer_id'] = trade[5] msg['seller_id'] = trade[6] msg['buyer_username'] = trade[7] msg['seller_username'] = trade[8] msg['created'] = trade[9] msg['trade_date'] = trade[9][:10] msg['trade_time'] = trade[9][11:] msg['order_id'] = trade[10] msg['counter_order_id'] = trade[11] Trade.create(self.db_session, msg) all_trades = Trade.get_all_trades(self.db_session) for t in all_trades: trade_info = dict() trade_info['price'] = t.price trade_info['size'] = t.size trade_info['trade_date'] = t.created.strftime('%Y-%m-%d') trade_info['trade_time'] = t.created.strftime('%H:%M:%S') self.md_subscriber[t.symbol].inst_status.push_trade(trade_info) for symbol, subscriber in self.md_subscriber.iteritems(): subscriber.ready() self.connections = {} self.heart_beat_timer = tornado.ioloop.PeriodicCallback( self.send_heartbeat_to_trade, 30000) self.heart_beat_timer.start() self.update_tor_nodes_timer = tornado.ioloop.PeriodicCallback( self.update_tor_nodes, 3600000) self.update_tor_nodes_timer.start()
def match(self, session, order, order_matcher_disabled=False): other_side = [] self_side = [] if order.is_buy: self_side = self.buy_side other_side = self.sell_side elif order.is_sell: other_side = self.buy_side self_side = self.sell_side execution_reports = [] trades_to_publish = [] execution_side = '1' if order.is_buy else '2' rpt_order = ExecutionReport( order, execution_side ) execution_reports.append( ( order.user_id, rpt_order.toJson() ) ) if order.user_id != order.account_id: execution_reports.append( ( order.account_id, rpt_order.toJson() ) ) is_last_match_a_partial_execution_on_counter_order = False execution_counter = 0 number_of_filled_counter_market_orders = 0 if not order_matcher_disabled: for execution_counter in xrange(0, len(other_side) + 1): if execution_counter == len(other_side): break # workaround to make the execution_counter be counted until the last order. if not order.leaves_qty > 0: break counter_order = other_side[execution_counter] if not order.has_match(counter_order): break # check for self execution if order.account_id == counter_order.account_id: # self execution.... let's cancel the counter order counter_order.cancel_qty( counter_order.leaves_qty ) # generate a cancel report cancel_rpt_counter_order = ExecutionReport( counter_order, execution_side ) execution_reports.append( ( counter_order.user_id, cancel_rpt_counter_order.toJson() ) ) if counter_order.user_id != counter_order.account_id: execution_reports.append( ( counter_order.account_id, cancel_rpt_counter_order.toJson() ) ) # go to the next order is_last_match_a_partial_execution_on_counter_order = False continue # Get the desired executed price and qty, by matching against the counter_order executed_qty = order.match( counter_order, order.leaves_qty) if counter_order.type == '1': # Market Order executed_price = order.price number_of_filled_counter_market_orders += 1 else: executed_price = counter_order.price # let's get the available qty to execute on the order side available_qty_on_order_side = order.get_available_qty_to_execute(session, '1' if order.is_buy else '2', executed_qty, executed_price ) qty_to_cancel_from_order = 0 if available_qty_on_order_side < executed_qty: # ops ... looks like the order.user didn't have enough to execute the order executed_qty = available_qty_on_order_side # cancel the remaining qty qty_to_cancel_from_order = order.leaves_qty - executed_qty # check if the order got fully cancelled if not executed_qty: order.cancel_qty( qty_to_cancel_from_order ) cancel_rpt_order = ExecutionReport( order, execution_side ) execution_reports.append( ( order.user_id, cancel_rpt_order.toJson() ) ) if order.user_id != order.account_id: execution_reports.append( ( order.account_id, cancel_rpt_order.toJson() ) ) break # let's get the available qty to execute on the counter side available_qty_on_counter_side = counter_order.get_available_qty_to_execute(session, '1' if counter_order.is_buy else '2', executed_qty, executed_price ) qty_to_cancel_from_counter_order = 0 if available_qty_on_counter_side < executed_qty: if qty_to_cancel_from_order: qty_to_cancel_from_order -= executed_qty - available_qty_on_order_side # ops ... looks like the counter_order.user didn't have enough to execute the order executed_qty = available_qty_on_counter_side # cancel the remaining qty qty_to_cancel_from_counter_order = counter_order.leaves_qty - executed_qty # check if the counter order was fully cancelled due the lack if not executed_qty: # just cancel the counter order, and go to the next order. counter_order.cancel_qty( qty_to_cancel_from_counter_order ) # generate a cancel report cancel_rpt_counter_order = ExecutionReport( counter_order, execution_side ) execution_reports.append( ( counter_order.user_id, cancel_rpt_counter_order.toJson() ) ) if counter_order.user_id != counter_order.account_id: execution_reports.append( ( counter_order.account_id, cancel_rpt_counter_order.toJson() ) ) # go to the next order is_last_match_a_partial_execution_on_counter_order = False continue # lets perform the execution if executed_qty: order.execute( executed_qty, executed_price ) counter_order.execute(executed_qty, executed_price ) trade = Trade.create(session, order, counter_order, self.symbol, executed_qty, executed_price ) trades_to_publish.append(trade) rpt_order = ExecutionReport( order, execution_side ) execution_reports.append( ( order.user_id, rpt_order.toJson() ) ) if order.user_id != order.account_id: execution_reports.append( ( order.account_id, rpt_order.toJson() ) ) rpt_counter_order = ExecutionReport( counter_order, execution_side ) execution_reports.append( ( counter_order.user_id, rpt_counter_order.toJson() ) ) if counter_order.user_id != counter_order.account_id: execution_reports.append( ( counter_order.account_id, rpt_counter_order.toJson() ) ) def generate_email_subject_and_body( session, order, trade ): from json import dumps from pyblinktrade.json_encoder import JsonEncoder from models import Currency qty_currency = order.symbol[:3] formatted_qty = Currency.format_number( session, qty_currency, trade.size / 1.e8 ) price_currency = order.symbol[3:] formatted_price = Currency.format_number( session, price_currency, trade.price / 1.e8 ) formatted_total_price = Currency.format_number( session, price_currency, trade.size/1.e8 * trade.price/1.e8 ) email_subject = 'E' email_template = "order-execution" email_params = { 'username': order.user.username, 'order_id': order.id, 'trade_id': trade.id, 'side': order.side, 'executed_when': trade.created, 'qty': formatted_qty, 'price': formatted_price, 'total': formatted_total_price } return email_subject, email_template, dumps(email_params, cls=JsonEncoder) email_data = generate_email_subject_and_body(session, order, trade) UserEmail.create( session = session, user_id = order.account_id, broker_id = order.broker_id, subject = email_data[0], template= email_data[1], language= order.email_lang, params = email_data[2]) email_data = generate_email_subject_and_body(session, counter_order, trade) UserEmail.create( session = session, user_id = counter_order.account_id, broker_id = counter_order.broker_id, subject = email_data[0], template= email_data[1], language= counter_order.email_lang, params = email_data[2]) # # let's do the partial cancels # # Cancel the qty from the current order if qty_to_cancel_from_order: order.cancel_qty(qty_to_cancel_from_order) # generate a cancel report cancel_rpt_order = ExecutionReport( order, execution_side ) execution_reports.append( ( order.user_id, cancel_rpt_order.toJson() ) ) if order.user_id != order.account_id: execution_reports.append( ( order.account_id, cancel_rpt_order.toJson() ) ) if qty_to_cancel_from_counter_order: counter_order.cancel_qty(qty_to_cancel_from_counter_order) # generate a cancel report cancel_rpt_counter_order = ExecutionReport( counter_order, execution_side ) execution_reports.append( ( counter_order.user_id, cancel_rpt_counter_order.toJson() ) ) if counter_order.user_id != counter_order.account_id: execution_reports.append( ( counter_order.account_id, cancel_rpt_counter_order.toJson() ) ) if counter_order.leaves_qty > 0: is_last_match_a_partial_execution_on_counter_order = True md_entry_type = '0' if order.is_buy else '1' counter_md_entry_type = '1' if order.is_buy else '0' # let's include the order in the book if the order is not fully executed. if order.leaves_qty > 0: insert_pos = bisect.bisect_right(self_side, order) self_side.insert( insert_pos, order ) if order.type == '2': # Limited orders go to the book. MarketDataPublisher.publish_new_order( self.symbol, md_entry_type , insert_pos, order) # don't send the first execution report (NEW) if the order was fully cancelled if order.is_cancelled and order.cum_qty == 0: execution_reports.pop(0) # Publish all execution reports for user_id, execution_report in execution_reports: TradeApplication.instance().publish( user_id, execution_report ) # Publish Market Data for the counter order if execution_counter: if is_last_match_a_partial_execution_on_counter_order: del other_side[0: execution_counter-1] MarketDataPublisher.publish_executions( self.symbol, counter_md_entry_type, execution_counter - 1 - number_of_filled_counter_market_orders, other_side[0] ) else: del other_side[0: execution_counter] MarketDataPublisher.publish_executions( self.symbol, counter_md_entry_type, execution_counter - number_of_filled_counter_market_orders ) if trades_to_publish: MarketDataPublisher.publish_trades(self.symbol, trades_to_publish) return ""
def match(self, session, order, order_matcher_disabled=False): other_side = [] self_side = [] if order.is_buy: self_side = self.buy_side other_side = self.sell_side elif order.is_sell: other_side = self.buy_side self_side = self.sell_side execution_reports = [] trades_to_publish = [] execution_side = '1' if order.is_buy else '2' rpt_order = ExecutionReport( order, execution_side ) execution_reports.append( ( order.user_id, rpt_order.toJson() ) ) if order.user_id != order.account_id: execution_reports.append( ( order.account_id, rpt_order.toJson() ) ) is_last_match_a_partial_execution_on_counter_order = False execution_counter = 0 number_of_filled_counter_market_orders = 0 if not order_matcher_disabled: for execution_counter in xrange(0, len(other_side) + 1): if execution_counter == len(other_side): break # workaround to make the execution_counter be counted until the last order. if not order.leaves_qty > 0: break counter_order = other_side[execution_counter] if not order.has_match(counter_order): break # check for self execution if order.account_id == counter_order.account_id: # self execution.... let's cancel the counter order counter_order.cancel_qty( counter_order.leaves_qty ) # generate a cancel report cancel_rpt_counter_order = ExecutionReport( counter_order, execution_side ) execution_reports.append( ( counter_order.user_id, cancel_rpt_counter_order.toJson() ) ) if counter_order.user_id != counter_order.account_id: execution_reports.append( ( counter_order.account_id, cancel_rpt_counter_order.toJson() ) ) # go to the next order is_last_match_a_partial_execution_on_counter_order = False continue # Get the desired executed price and qty, by matching against the counter_order executed_qty = order.match( counter_order, order.leaves_qty) if counter_order.type == '1': # Market Order executed_price = order.price number_of_filled_counter_market_orders += 1 else: executed_price = counter_order.price # let's get the available qty to execute on the order side available_qty_on_order_side = order.get_available_qty_to_execute(session, '1' if order.is_buy else '2', executed_qty, executed_price ) qty_to_cancel_from_order = 0 if available_qty_on_order_side < executed_qty: # ops ... looks like the order.user didn't have enough to execute the order executed_qty = available_qty_on_order_side # cancel the remaining qty qty_to_cancel_from_order = order.leaves_qty - executed_qty # check if the order got fully cancelled if not executed_qty: order.cancel_qty( qty_to_cancel_from_order ) cancel_rpt_order = ExecutionReport( order, execution_side ) execution_reports.append( ( order.user_id, cancel_rpt_order.toJson() ) ) if order.user_id != order.account_id: execution_reports.append( ( order.account_id, cancel_rpt_order.toJson() ) ) break # let's get the available qty to execute on the counter side available_qty_on_counter_side = counter_order.get_available_qty_to_execute(session, '1' if counter_order.is_buy else '2', executed_qty, executed_price ) qty_to_cancel_from_counter_order = 0 if available_qty_on_counter_side < executed_qty: if qty_to_cancel_from_order: qty_to_cancel_from_order -= executed_qty - available_qty_on_order_side # ops ... looks like the counter_order.user didn't have enough to execute the order executed_qty = available_qty_on_counter_side # cancel the remaining qty qty_to_cancel_from_counter_order = counter_order.leaves_qty - executed_qty # check if the counter order was fully cancelled due the lack if not executed_qty: # just cancel the counter order, and go to the next order. counter_order.cancel_qty( qty_to_cancel_from_counter_order ) # generate a cancel report cancel_rpt_counter_order = ExecutionReport( counter_order, execution_side ) execution_reports.append( ( counter_order.user_id, cancel_rpt_counter_order.toJson() ) ) if counter_order.user_id != counter_order.account_id: execution_reports.append( ( counter_order.account_id, cancel_rpt_counter_order.toJson() ) ) # go to the next order is_last_match_a_partial_execution_on_counter_order = False continue # lets perform the execution if executed_qty: order.execute( executed_qty, executed_price ) counter_order.execute(executed_qty, executed_price ) trade = Trade.create(session, order, counter_order, self.symbol, executed_qty, executed_price ) trades_to_publish.append(trade) rpt_order = ExecutionReport( order, execution_side ) execution_reports.append( ( order.user_id, rpt_order.toJson() ) ) if order.user_id != order.account_id: execution_reports.append( ( order.account_id, rpt_order.toJson() ) ) rpt_counter_order = ExecutionReport( counter_order, execution_side ) execution_reports.append( ( counter_order.user_id, rpt_counter_order.toJson() ) ) if counter_order.user_id != counter_order.account_id: execution_reports.append( ( counter_order.account_id, rpt_counter_order.toJson() ) ) def generate_email_subject_and_body( session, order, trade ): from json import dumps from pyblinktrade.json_encoder import JsonEncoder from models import Currency qty_currency = order.symbol[:3] formatted_qty = Currency.format_number( session, qty_currency, trade.size / 1.e8 ) price_currency = order.symbol[3:] formatted_price = Currency.format_number( session, price_currency, trade.price / 1.e8 ) formatted_total_price = Currency.format_number( session, price_currency, trade.size/1.e8 * trade.price/1.e8 ) email_subject = 'E' email_template = "order-execution" email_params = { 'username': order.user.username, 'order_id': order.id, 'trade_id': trade.id, 'side': order.side, 'executed_when': trade.created, 'qty': formatted_qty, 'price': formatted_price, 'total': formatted_total_price } return email_subject, email_template, dumps(email_params, cls=JsonEncoder) email_data = generate_email_subject_and_body(session, counter_order, trade) UserEmail.create( session = session, user_id = counter_order.account_id, broker_id = counter_order.broker_id, subject = email_data[0], template= email_data[1], language= counter_order.email_lang, params = email_data[2]) # # let's do the partial cancels # # Cancel the qty from the current order if qty_to_cancel_from_order: order.cancel_qty(qty_to_cancel_from_order) # generate a cancel report cancel_rpt_order = ExecutionReport( order, execution_side ) execution_reports.append( ( order.user_id, cancel_rpt_order.toJson() ) ) if order.user_id != order.account_id: execution_reports.append( ( order.account_id, cancel_rpt_order.toJson() ) ) if qty_to_cancel_from_counter_order: counter_order.cancel_qty(qty_to_cancel_from_counter_order) # generate a cancel report cancel_rpt_counter_order = ExecutionReport( counter_order, execution_side ) execution_reports.append( ( counter_order.user_id, cancel_rpt_counter_order.toJson() ) ) if counter_order.user_id != counter_order.account_id: execution_reports.append( ( counter_order.account_id, cancel_rpt_counter_order.toJson() ) ) if counter_order.leaves_qty > 0: is_last_match_a_partial_execution_on_counter_order = True md_entry_type = '0' if order.is_buy else '1' counter_md_entry_type = '1' if order.is_buy else '0' # let's include the order in the book if the order is not fully executed. if order.leaves_qty > 0: insert_pos = bisect.bisect_right(self_side, order) self_side.insert( insert_pos, order ) if order.type == '2': # Limited orders go to the book. MarketDataPublisher.publish_new_order( self.symbol, md_entry_type , insert_pos, order) # don't send the first execution report (NEW) if the order was fully cancelled if order.is_cancelled and order.cum_qty == 0: execution_reports.pop(0) # Publish all execution reports for user_id, execution_report in execution_reports: TradeApplication.instance().publish( user_id, execution_report ) # Publish Market Data for the counter order if execution_counter: if is_last_match_a_partial_execution_on_counter_order: del other_side[0: execution_counter-1] MarketDataPublisher.publish_executions( self.symbol, counter_md_entry_type, execution_counter - 1 - number_of_filled_counter_market_orders, other_side[0] ) else: del other_side[0: execution_counter] MarketDataPublisher.publish_executions( self.symbol, counter_md_entry_type, execution_counter - number_of_filled_counter_market_orders ) if trades_to_publish: MarketDataPublisher.publish_trades(self.symbol, trades_to_publish) return ""
def __init__(self, opt): handlers = [ (r'/', WebSocketHandler), (r'/get_deposit(.*)', DepositHandler), (r'/_webhook/verification_form', VerificationWebHookHandler), (r'/_webhook/deposit_receipt', DepositReceiptWebHookHandler), (r'/process_deposit(.*)', ProcessDepositHandler), (r'/api/(?P<version>[^\/]+)/(?P<symbol>[^\/]+)/(?P<resource>[^\/]+)', RestApiHandler) ] settings = dict(cookie_secret='cookie_secret') tornado.web.Application.__init__(self, handlers, **settings) self.replay_logger = logging.getLogger("REPLAY") self.replay_logger.setLevel(logging.INFO) self.replay_logger.addHandler(input_log_file_handler) self.replay_logger.info('START') self.log_start_data() from models import ENGINE, db_bootstrap self.db_session = scoped_session(sessionmaker(bind=ENGINE)) db_bootstrap(self.db_session) self.zmq_context = zmq.Context() self.trade_in_socket = self.zmq_context.socket(zmq.REQ) self.trade_in_socket.connect(opt.trade_in) self.application_trade_client = TradeClient(self.zmq_context, self.trade_in_socket) self.application_trade_client.connect() instruments = self.application_trade_client.getSecurityList() self.md_subscriber = {} for instrument in instruments: symbol = instrument['Symbol'] self.md_subscriber[symbol] = MarketDataSubscriber.get(symbol, self) self.md_subscriber[symbol].subscribe(self.zmq_context, options.trade_pub, self.application_trade_client) last_trade_id = Trade.get_last_trade_id() trade_list = self.application_trade_client.getLastTrades(last_trade_id) for trade in trade_list: msg = dict() msg['id'] = trade[0] msg['symbol'] = trade[1] msg['side'] = trade[2] msg['price'] = trade[3] msg['size'] = trade[4] msg['buyer_username'] = trade[5] msg['seller_username'] = trade[6] msg['created'] = trade[7] msg['trade_date'] = trade[7][:10] msg['trade_time'] = trade[7][11:] msg['order_id'] = trade[8] msg['counter_order_id'] = trade[9] Trade.create(self.db_session, msg) all_trades = Trade.get_all_trades(self.db_session) for t in all_trades: trade_info = dict() trade_info['price'] = t.price trade_info['size'] = t.size trade_info['trade_date'] = t.created.strftime('%Y-%m-%d') trade_info['trade_time'] = t.created.strftime('%H:%M:%S') self.md_subscriber[t.symbol].inst_status.push_trade(trade_info) for symbol, subscriber in self.md_subscriber.iteritems(): subscriber.ready() self.connections = {} self.heart_beat_timer = tornado.ioloop.PeriodicCallback( self.send_heartbeat_to_trade, 30000) self.heart_beat_timer.start()
def __init__(self, opt, instance_name): self.options = opt self.instance_name = instance_name handlers = [ (r'/', WebSocketHandler), (r'/get_deposit(.*)', DepositHandler), (r'/_webhook/verification_form', VerificationWebHookHandler), (r'/_webhook/deposit_receipt', DepositReceiptWebHookHandler), (r'/process_deposit(.*)', ProcessDepositHandler), (r'/api/(?P<version>[^\/]+)/(?P<symbol>[^\/]+)/(?P<resource>[^\/]+)', RestApiHandler) ] settings = dict( cookie_secret='cookie_secret' ) tornado.web.Application.__init__(self, handlers, **settings) self.allowed_origins = json.loads(self.options.allowed_origins) self.allow_all_origins = self.allowed_origins[0] == '*' input_log_file_handler = logging.handlers.TimedRotatingFileHandler( os.path.expanduser(self.options.gateway_log), when='MIDNIGHT') formatter = logging.Formatter('%(asctime)s - %(message)s') input_log_file_handler.setFormatter(formatter) self.replay_logger = logging.getLogger(self.instance_name) self.replay_logger.setLevel(logging.INFO) self.replay_logger.addHandler(input_log_file_handler) ch = logging.StreamHandler(sys.stdout) ch.setLevel(logging.DEBUG) ch.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')) self.replay_logger.addHandler(ch) self.replay_logger.info('START') self.log_start_data() from models import Base, db_bootstrap db_engine = self.options.sqlalchemy_engine + ':///' +\ os.path.expanduser(self.options.sqlalchemy_connection_string) engine = create_engine( db_engine, echo=self.options.db_echo) Base.metadata.create_all(engine) self.db_session = scoped_session(sessionmaker(bind=engine)) db_bootstrap(self.db_session) self.zmq_context = zmq.Context() self.trade_in_socket = self.zmq_context.socket(zmq.REQ) self.trade_in_socket.connect(self.options.trade_in) self.application_trade_client = TradeClient( self.zmq_context, self.trade_in_socket) self.application_trade_client.connect() self.security_list = self.application_trade_client.getSecurityList() self.md_subscriber = {} for instrument in self.security_list.get('Instruments'): symbol = instrument['Symbol'] self.md_subscriber[symbol] = MarketDataSubscriber.get(symbol, self) self.md_subscriber[symbol].subscribe( self.zmq_context, self.options.trade_pub, self.application_trade_client) last_trade_id = Trade.get_last_trade_id(self.db_session) trade_list = self.application_trade_client.getLastTrades(last_trade_id) for trade in trade_list: msg = dict() msg['id'] = trade[0] msg['symbol'] = trade[1] msg['side'] = trade[2] msg['price'] = trade[3] msg['size'] = trade[4] msg['buyer_id'] = trade[5] msg['seller_id'] = trade[6] msg['buyer_username'] = trade[7] msg['seller_username'] = trade[8] msg['created'] = trade[9] msg['trade_date'] = trade[9][:10] msg['trade_time'] = trade[9][11:] msg['order_id'] = trade[10] msg['counter_order_id'] = trade[11] Trade.create( self.db_session, msg) all_trades = Trade.get_all_trades(self.db_session) for t in all_trades: trade_info = dict() trade_info['price'] = t.price trade_info['size'] = t.size trade_info['trade_date'] = t.created.strftime('%Y-%m-%d') trade_info['trade_time'] = t.created.strftime('%H:%M:%S') self.md_subscriber[ t.symbol ].inst_status.push_trade(trade_info) for symbol, subscriber in self.md_subscriber.iteritems(): subscriber.ready() self.connections = {} self.heart_beat_timer = tornado.ioloop.PeriodicCallback( self.send_heartbeat_to_trade, 30000) self.heart_beat_timer.start()
def __init__(self, opt): handlers = [ (r'/', WebSocketHandler), (r'/get_deposit(.*)', DepositHandler), (r'/_webhook/verification_form', VerificationWebHookHandler), (r'/_webhook/deposit_receipt', DepositReceiptWebHookHandler), (r'/process_deposit(.*)', ProcessDepositHandler), (r'/api/(?P<version>[^\/]+)/(?P<symbol>[^\/]+)/(?P<resource>[^\/]+)', RestApiHandler) ] settings = dict( cookie_secret='cookie_secret' ) tornado.web.Application.__init__(self, handlers, **settings) self.replay_logger = logging.getLogger("REPLAY") self.replay_logger.setLevel(logging.INFO) self.replay_logger.addHandler(input_log_file_handler) self.replay_logger.info('START') self.log_start_data() from models import ENGINE, db_bootstrap self.db_session = scoped_session(sessionmaker(bind=ENGINE)) db_bootstrap(self.db_session) self.zmq_context = zmq.Context() self.trade_in_socket = self.zmq_context.socket(zmq.REQ) self.trade_in_socket.connect(opt.trade_in) self.application_trade_client = TradeClient( self.zmq_context, self.trade_in_socket) self.application_trade_client.connect() instruments = self.application_trade_client.getSecurityList() self.md_subscriber = {} for instrument in instruments: symbol = instrument['Symbol'] self.md_subscriber[symbol] = MarketDataSubscriber.get(symbol, self) self.md_subscriber[symbol].subscribe( self.zmq_context, options.trade_pub, self.application_trade_client) last_trade_id = Trade.get_last_trade_id() trade_list = self.application_trade_client.getLastTrades(last_trade_id) for trade in trade_list: msg = dict() msg['id'] = trade[0] msg['symbol'] = trade[1] msg['side'] = trade[2] msg['price'] = trade[3] msg['size'] = trade[4] msg['buyer_username'] = trade[5] msg['seller_username'] = trade[6] msg['created'] = trade[7] msg['trade_date'] = trade[7][:10] msg['trade_time'] = trade[7][11:] msg['order_id'] = trade[8] msg['counter_order_id'] = trade[9] Trade.create( self.db_session, msg) all_trades = Trade.get_all_trades(self.db_session) for t in all_trades: trade_info = dict() trade_info['price'] = t.price trade_info['size'] = t.size trade_info['trade_date'] = t.created.strftime('%Y-%m-%d') trade_info['trade_time'] = t.created.strftime('%H:%M:%S') self.md_subscriber[ t.symbol ].inst_status.push_trade(trade_info) for symbol, subscriber in self.md_subscriber.iteritems(): subscriber.ready() self.connections = {} self.heart_beat_timer = tornado.ioloop.PeriodicCallback( self.send_heartbeat_to_trade, 30000) self.heart_beat_timer.start()