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

        self.lock()
        mki = self._pending_market_info_insert
        self._pending_market_info_insert = []
        self.unlock()

        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

                    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 = %s,
                                        market_type = %s, unit_type = %s, contract_type = %s,
                                        trade_type = %s, orders = %s,
                                        base = %s, base_display = %s, base_precision = %s,
                                        quote = %s, quote_display = %s, quote_precision = %s,
                                        expiry = %s, timestamp = %s,
                                        lot_size = %s, contract_size = %s, base_exchange_rate = %s,
                                        value_per_pip = %s, one_pip_means = %s, margin_factor = %s,
                                        min_size = %s, max_size = %s, step_size = %s,
                                        min_notional = %s, max_notional = %s, step_notional = %s,
                                        min_price = %s, max_price = %s, step_price = %s,
                                        maker_fee = %s, taker_fee = %s, maker_commission = %s, taker_commission = %s""",
                                    (*mi, *mi[2:]))

                self._db.commit()
            except Exception as e:
                logger.error(repr(e))

                # retry the next time
                self.lock()
                self._pending_market_info_insert = mki + self._pending_market_info_insert
                self.unlock()

        #
        # select market info
        #

        self.lock()
        mis = self._pending_market_info_select
        self._pending_market_info_select = []
        self.unlock()

        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])

                        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 Exception as e:
                logger.error(repr(e))

                # retry the next time
                self.lock()
                self._pending_market_info_select = mis + self._pending_market_info_select
                self.unlock()

        #
        # select market list
        #

        self.lock()
        mls = self._pending_market_list_select
        self._pending_market_list_select = []
        self.unlock()

        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 Exception as e:
                logger.error(repr(e))

                # retry the next time
                self.lock()
                self._pending_market_list_select = mls + self._pending_market_list_select
                self.unlock()
Beispiel #2
0
    def fetch_market(self, market_id):
        """
        Fetch and cache it.
        @param market_id Is the IG epic name
        """
        market_info = self._ig_service.fetch_market_by_epic(market_id)
        if not market_info:
            return

        instrument = market_info['instrument']
        snapshot = market_info['snapshot']
        dealing_rules = market_info['dealingRules']

        market = Market(market_id, instrument['marketId'])

        # cannot interpret this value because IG want it as it is
        market.expiry = instrument['expiry']

        # not perfect but IG does not provides this information
        if instrument["marketId"].endswith(
                instrument["currencies"][0]["name"]):
            base_symbol = instrument[
                "marketId"][:-len(instrument["currencies"][0]["name"])]
        else:
            base_symbol = instrument["marketId"]

        market.base_exchange_rate = instrument['currencies'][0][
            'baseExchangeRate']  # "exchangeRate": 0.77

        market.one_pip_means = float(instrument['onePipMeans'].split(' ')[0])
        market.value_per_pip = float(instrument['valueOfOnePip'])
        market.contract_size = float(instrument['contractSize'])
        market.lot_size = float(instrument['lotSize'])

        # @todo how to determine base precision ?
        market.set_base(base_symbol, base_symbol)
        market.set_quote(
            instrument["currencies"][0]["name"],
            instrument["currencies"][0]['symbol'],
            -int(math.log10(market.one_pip_means)))  # "USD", "$", precision

        if snapshot:
            market.is_open = snapshot["marketStatus"] == "TRADEABLE"
            market.bid = snapshot['bid']
            market.ofr = snapshot['offer']

        # "marginFactorUnit": "PERCENTAGE" not avalaible if market is down
        if instrument.get('marginFactor') and market.is_open:
            market.margin_factor = float(instrument['marginFactor'])
            margin_factor = instrument['marginFactor']
        elif instrument.get('margin') and market.is_open:
            market.margin_factor = 0.1 / float(instrument['margin'])
            margin_factor = str(market.margin_factor)
        else:
            # we don't want this when market is down because it could overwrite the previous stored value
            margin_factor = None

        if instrument['unit'] == 'AMOUNT':
            market.unit_type = Market.UNIT_AMOUNT
        elif instrument['unit'] == 'CONTRACTS':
            market.unit_type = Market.UNIT_CONTRACTS
        elif instrument['unit'] == 'SHARES':
            market.unit_type = Market.UNIT_SHARES

        # BINARY OPT_* BUNGEE_*
        if instrument['type'] == 'CURRENCIES':
            market._market_type = Market.TYPE_CURRENCY
        elif instrument['type'] == 'INDICES':
            market._market_type = Market.TYPE_INDICE
        elif instrument['type'] == 'COMMODITIES':
            market._market_type = Market.TYPE_COMMODITY
        elif instrument['type'] == 'SHARES':
            market._market_type = Market.TYPE_STOCK
        elif instrument['type'] == 'RATES':
            market._market_type = Market.TYPE_RATE
        elif instrument['type'] == 'SECTORS':
            market._market_type = Market.TYPE_SECTOR

        market.trade = Market.TRADE_MARGIN
        market.contract_type = Market.CONTRACT_CFD

        # take minDealSize as tick size
        market.set_size_limits(dealing_rules["minDealSize"]["value"], 0.0,
                               dealing_rules["minDealSize"]["value"])
        # @todo there is some limits in contract size
        market.set_notional_limits(0.0, 0.0, 0.0)
        # @todo maybe decimal_place of onePipMeans for tick_size
        market.set_price_limits(0.0, 0.0, 0.0)

        # commission for stocks
        commission = "0.0"
        # @todo

        # store it
        self.lock()
        self._markets[market_id] = market
        self.unlock()

        # store market info
        Database.inst().store_market_info((
            self.name,
            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
            instrument['lotSize'],
            instrument['contractSize'],
            str(market.base_exchange_rate),
            instrument['valueOfOnePip'],
            instrument['onePipMeans'].split(' ')[0],
            margin_factor,
            dealing_rules["minDealSize"]["value"],
            "0.0",
            dealing_rules["minDealSize"]["value"],  # size limits
            "0.0",
            "0.0",
            "0.0",  # notional limits
            "0.0",
            "0.0",
            "0.0",  # price limits
            "0.0",
            "0.0",
            commission,
            commission)  # fees
                                          )