Beispiel #1
0
    def process_market(self):
        #
        # insert market info
        #

        with self._mutex:
            mki = self._pending_market_info_insert
            self._pending_market_info_insert = []
    
        if mki:
            try:
                cursor = self._db.cursor()

                for mi in mki:
                    if mi[16] is None:
                        # margin factor is unavailable when market is down, so use previous value if available
                        cursor.execute("""SELECT margin_factor FROM market WHERE broker_id = '%s' AND market_id = '%s'""" % (mi[0], mi[1]))
                        row = cursor.fetchone()

                        if row:
                            # replace by previous margin factor from the DB
                            margin_factor = row[0]
                            mi = list(mi)
                            mi[16] = margin_factor
                        else:
                            mi[16] = "1.0"

                    cursor.execute("""INSERT INTO market(broker_id, market_id, symbol,
                                        market_type, unit_type, contract_type,
                                        trade_type, orders,
                                        base, base_display, base_precision,
                                        quote, quote_display, quote_precision,
                                        expiry, timestamp,
                                        lot_size, contract_size, base_exchange_rate,
                                        value_per_pip, one_pip_means, margin_factor,
                                        min_size, max_size, step_size,
                                        min_notional, max_notional, step_notional,
                                        min_price, max_price, step_price,
                                        maker_fee, taker_fee, maker_commission, taker_commission) 
                                    VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
                                    ON CONFLICT (broker_id, market_id) DO UPDATE SET symbol = EXCLUDED.symbol,
                                        market_type = EXCLUDED.market_type, unit_type = EXCLUDED.unit_type, contract_type = EXCLUDED.contract_type,
                                        trade_type = EXCLUDED.trade_type, orders = EXCLUDED.orders,
                                        base = EXCLUDED.base, base_display = EXCLUDED.base_display, base_precision = EXCLUDED.base_precision,
                                        quote = EXCLUDED.quote, quote_display = EXCLUDED.quote_display, quote_precision = EXCLUDED.quote_precision,
                                        expiry = EXCLUDED.expiry, timestamp = EXCLUDED.timestamp,
                                        lot_size = EXCLUDED.lot_size, contract_size = EXCLUDED.contract_size, base_exchange_rate = EXCLUDED.base_exchange_rate,
                                        value_per_pip = EXCLUDED.value_per_pip, one_pip_means = EXCLUDED.one_pip_means, margin_factor = EXCLUDED.margin_factor,
                                        min_size = EXCLUDED.min_size, max_size = EXCLUDED.max_size, step_size = EXCLUDED.step_size,
                                        min_notional = EXCLUDED.min_notional, max_notional = EXCLUDED.max_notional, step_notional = EXCLUDED.step_notional,
                                        min_price = EXCLUDED.min_price, max_price = EXCLUDED.max_price, step_price = EXCLUDED.step_price,
                                        maker_fee = EXCLUDED.maker_fee, taker_fee = EXCLUDED.taker_fee, maker_commission = EXCLUDED.maker_commission, taker_commission = EXCLUDED.taker_commission""",
                                    (*mi,))

                self._db.commit()
            except self.psycopg2.OperationalError as e:
                self.try_reconnect(e)

                # retry the next time
                with self._mutex:
                    self._pending_market_info_insert = mki + self._pending_market_info_insert

            except Exception as e:
                self.on_error(e)

                # retry the next time
                with self._mutex:
                    self._pending_market_info_insert = mki + self._pending_market_info_insert

        #
        # select market info
        #

        with self._mutex:
            mis = self._pending_market_info_select
            self._pending_market_info_select = []

        if mis:
            try:
                cursor = self._db.cursor()

                for mi in mis:
                    cursor.execute("""SELECT symbol,
                                        market_type, unit_type, contract_type,
                                        trade_type, orders,
                                        base, base_display, base_precision,
                                        quote, quote_display, quote_precision,
                                        expiry, timestamp,
                                        lot_size, contract_size, base_exchange_rate,
                                        value_per_pip, one_pip_means, margin_factor,
                                        min_size, max_size, step_size,
                                        min_notional, max_notional, step_notional,
                                        min_price, max_price, step_price,
                                        maker_fee, taker_fee, maker_commission, taker_commission FROM market
                                    WHERE broker_id = '%s' AND market_id = '%s'""" % (
                                        mi[1], mi[2]))

                    row = cursor.fetchone()

                    if row:
                        market_info = Market(mi[2], row[0])

                        market_info.is_open = True

                        market_info.market_type = row[1]
                        market_info.unit_type = row[2]
                        market_info.contract_type = row[3]

                        market_info.trade = row[4]
                        market_info.orders = row[5]

                        market_info.set_base(row[6], row[7], int(row[8]))
                        market_info.set_quote(row[9], row[10], int(row[11]))

                        market_info.expiry = row[12]
                        market_info.last_update_time = row[13] * 0.001

                        market_info.lot_size = float(row[14])
                        market_info.contract_size = float(row[15])
                        market_info.base_exchange_rate = float(row[16])
                        market_info.value_per_pip = float(row[17])
                        market_info.one_pip_means = float(row[18])

                        if row[19] is not None or row[19] is not 'None':
                            if row[19] == '-':  # not defined mean 1.0 or no margin
                                market_info.margin_factor = 1.0
                            else:
                                market_info.margin_factor = float(row[19] or "1.0")

                        market_info.set_size_limits(float(row[20]), float(row[21]), float(row[22]))
                        market_info.set_notional_limits(float(row[23]), float(row[24]), float(row[25]))
                        market_info.set_price_limits(float(row[26]), float(row[27]), float(row[28]))

                        market_info.maker_fee = float(row[29])
                        market_info.taker_fee = float(row[30])

                        market_info.maker_commission = float(row[31])
                        market_info.taker_commission = float(row[32])
                    else:
                        market_info = None

                    # notify
                    mi[0].notify(Signal.SIGNAL_MARKET_INFO_DATA, mi[1], (mi[2], market_info))
            except self.psycopg2.OperationalError as e:
                self.try_reconnect(e)

                # retry the next time
                with self._mutex:
                    self._pending_market_info_select = mis + self._pending_market_info_select

            except Exception as e:
                self.on_error(e)

                # retry the next time
                with self._mutex:
                    self._pending_market_info_select = mis + self._pending_market_info_select

        #
        # select market list
        #

        with self._mutex:
            mls = self._pending_market_list_select
            self._pending_market_list_select = []

        if mls:
            try:
                cursor = self._db.cursor()

                for m in mls:
                    cursor.execute("""SELECT market_id, symbol, base, quote FROM market WHERE broker_id = '%s'""" % (m[1],))

                    rows = cursor.fetchall()

                    market_list = []

                    for row in rows:
                        market_list.append(row)

                    # notify
                    m[0].notify(Signal.SIGNAL_MARKET_LIST_DATA, m[1], market_list)
            except self.psycopg2.OperationalError as e:
                self.try_reconnect(e)

                # retry the next time
                with self._mutex:
                    self._pending_market_list_select = mls + self._pending_market_list_select
            except Exception as e:
                self.on_error(e)

                # retry the next time
                with self._mutex:
                    self._pending_market_list_select = mls + self._pending_market_list_select
Beispiel #2
0
    def install_market_data(self, market_id, market_data):
        """
        Install a market info data into the database.
        """
        market = Market(market_id, market_data.get('symbol', market_id))

        market.base_exchange_rate = market_data.get('base-exchange-rate', 1.0)

        market.one_pip_means = market_data.get('one-pip-means', 1.0)
        market.value_per_pip = market_data.get('value-per-pip', 1.0)
        market.contract_size = market_data.get('contract-size', 1.0)
        market.lot_size = market_data.get('lot-size', 1.0)

        market.expiry = market_data.get('expiry', '-')

        base = market_data.get('base', {})
        market.set_base(base.get('symbol', 'USD'), base.get('display', '$'),
                        base.get('precision', 2))

        quote = market_data.get('quote', {})
        market.set_base(quote.get('symbol', 'USD'), quote.get('display', '$'),
                        quote.get('precision', 2))

        market.is_open = True

        market.margin_factor = market_data.get('margin-factor', 1.0)

        if 'unit' in market_data:
            if market_data['unit'] == 'amount':
                market.unit_type = Market.UNIT_AMOUNT
            elif market_data['unit'] == 'contracts':
                market.unit_type = Market.UNIT_CONTRACTS
            elif market_data['unit'] == 'shares':
                market.unit_type = Market.UNIT_SHARES
            else:
                market.unit_type = Market.UNIT_CONTRACTS
        else:
            market.unit_type = Market.UNIT_CONTRACTS

        if 'type' in market_data:
            if market_data['type'] == 'currency':
                market.market_type = Market.TYPE_CURRENCY
            elif market_data['type'] == 'indice':
                market.market_type = Market.TYPE_INDICE
            elif market_data['type'] == 'commodity':
                market.market_type = Market.TYPE_COMMODITY
            elif market_data['type'] == 'stock':
                market.market_type = Market.TYPE_STOCK
            elif market_data['type'] == 'rate':
                market.market_type = Market.TYPE_RATE
            elif market_data['type'] == 'sector':
                market.market_type = Market.TYPE_SECTOR
            else:
                market.market_type = Market.TYPE_UNKNOWN
        else:
            market.market_type = Market.TYPE_UNKNOWN

        if 'contract' in market_data:
            if market_data['contract'] == 'spot':
                market.contract_type = Market.CONTRACT_SPOT
            elif market_data['contract'] == 'cfd':
                market.contract_type = Market.CONTRACT_CFD
            elif market_data['contract'] == 'futur':
                market.contract_type = Market.CONTRACT_FUTUR
            elif market_data['contract'] == 'option':
                market.contract_type = Market.CONTRACT_OPTION
            elif market_data['contract'] == 'warrant':
                market.contract_type = Market.CONTRACT_WARRANT
            elif market_data['contract'] == 'turbo':
                market.contract_type = Market.CONTRACT_TURBO
            else:
                market.contract_type = Market.CONTRACT_SPOT
        else:
            market.contract_type = Market.CONTRACT_SPOT

        market.trade = 0

        if market_data.get('spot', False):
            market.trade |= Market.TRADE_BUY_SELL
        if market_data.get('margin', False):
            market.trade |= Market.TRADE_MARGIN
        if market_data.get('indivisible', False):
            market.trade |= Market.TRADE_IND_MARGIN
        if market_data.get('fifo', False):
            market.trade |= Market.TRADE_FIFO
        if market_data.get('position', False):
            market.trade |= Market.TRADE_POSITION

        orders = market_data.get(
            'orders', ('market', 'limit', 'stop-market', 'stop-limit',
                       'take-profit-market', 'take-profit-limit'))

        if 'market' in orders:
            market.orders |= Market.ORDER_MARKET
        if 'limit' in orders:
            market.orders |= Market.ORDER_LIMIT
        if 'stop-market' in orders:
            market.orders |= Market.ORDER_STOP_MARKET
        if 'stop-limit' in orders:
            market.orders |= Market.ORDER_STOP_LIMIT
        if 'take-profit-market' in orders:
            market.orders |= Market.ORDER_TAKE_PROFIT_MARKET
        if 'take-profit-limit' in orders:
            market.orders |= Market.ORDER_TAKE_PROFIT_LIMIT
        if 'one-cancel-other' in orders:
            market.orders |= Market.ORDER_ONE_CANCEL_OTHER

        size_limits = market_data.get('size-limits', {
            'min': 0.0,
            'max': 0.0,
            'step': 0.0
        })
        market.set_size_limits(size_limits.get('min', 0.0),
                               size_limits.get('max', 0.0),
                               size_limits.get('step', 0.0))

        notional_limits = market_data.get('notional-limits', {
            'min': 0.0,
            'max': 0.0,
            'step': 0.0
        })
        market.set_size_limits(notional_limits.get('min', 0.0),
                               notional_limits.get('max', 0.0),
                               notional_limits.get('step', 0.0))

        price_limits = market_data.get('price-limits', {
            'min': 0.0,
            'max': 0.0,
            'step': 0.0
        })
        market.set_size_limits(price_limits.get('min', 0.0),
                               price_limits.get('max', 0.0),
                               price_limits.get('step', 0.0))

        # fees & commissions
        fees = market_data.get('fees', {})
        market.maker_fee = fees.get('maker', 0.0)
        market.taker_fee = fees.get('taker', 0.0)

        commissions = market_data.get('commissions', {})
        market.maker_commission = commissions.get('maker', 0.0)
        market.taker_commission = commissions.get('maker', 0.0)

        # store the last market info to be used for backtesting
        Database.inst().store_market_info((
            self.name,
            market.market_id,
            market.symbol,
            market.market_type,
            market.unit_type,
            market.contract_type,  # type
            market.trade,
            market.orders,  # type
            market.base,
            market.base_display,
            market.base_precision,  # base
            market.quote,
            market.quote_display,
            market.quote_precision,  # quote
            market.expiry,
            int(market.last_update_time * 1000.0),  # expiry, timestamp
            str(market.lot_size),
            str(market.contract_size),
            str(market.base_exchange_rate),
            str(market.value_per_pip),
            str(market.one_pip_means),
            str(market.margin_factor),
            str(market.min_size),
            str(market.max_size),
            str(market.step_size),  # size limits
            str(market.min_notional),
            str(market.max_notional),
            str(market.step_notional),  # notional limits
            str(market.min_price),
            str(market.max_price),
            str(market.tick_price),  # price limits
            str(market.maker_fee),
            str(market.taker_fee),
            str(market.maker_commission),
            str(market.taker_commission))  # fees
                                          )