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 DUPLICATE KEY UPDATE 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()
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 )