예제 #1
0
    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))
예제 #2
0
파일: trade.py 프로젝트: Textrade/Textrade
 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
     )
예제 #3
0
파일: trade.py 프로젝트: Textrade/Textrade
 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
     )
예제 #4
0
    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
예제 #5
0
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))
예제 #6
0
    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)
예제 #7
0
    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)
예제 #8
0
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))
예제 #9
0
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)
예제 #10
0
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)
예제 #11
0
    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
예제 #12
0
    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()
예제 #13
0
  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 ""
예제 #14
0
  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 ""
예제 #15
0
    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()
예제 #16
0
파일: main.py 프로젝트: bitcoinland/bitex
    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()
예제 #17
0
    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()