Ejemplo n.º 1
0
    def fetch_market(self, epic):
        """
        Fetch and cache it. It rarely changes, except for base exchange rate, so assume it once for all.
        """
        market_info = self._connector.market(epic)

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

        market = Market(epic, 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])  # "1 Index Point", "0.0001 USD/EUR"
        market.value_per_pip = float(instrument['valueOfOnePip'])
        market.contract_size = float(instrument['contractSize'])
        market.lot_size = float(instrument['lotSize'])

        market.set_base(
            base_symbol,
            base_symbol,
            decimal_place(market.one_pip_means))

        if instrument['type'] in ('CURRENCIES'):
            pass  # quote_precision = 
        elif instrument['type'] in ('INDICES', 'COMMODITIES', 'SHARES', 'RATES', 'SECTORS'):
            pass  # quote_precision = 

        market.set_quote(
            instrument["currencies"][0]["name"],
            instrument["currencies"][0]['symbol'],
            decimal_place(market.one_pip_means))

        # "forceOpenAllowed": true,
        # "stopsLimitsAllowed": true,
        # "controlledRiskAllowed": true,
        # "streamingPricesAvailable": true,

        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.TRADE_POSITION
        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)
        # use one pip means for minimum and tick price size
        market.set_price_limits(market.one_pip_means, 0.0, market.one_pip_means)

        # commission for stocks @todo
        commission = "0.0"

        # store the last market info to be used for backtesting
        if not self._read_only:
            Database.inst().store_market_info((self.name, epic, 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
            )

        # print(market.symbol, market._size_limits, market._price_limits)

        # notify for strategy
        self.service.notify(Signal.SIGNAL_MARKET_INFO_DATA, self.name, (epic, market))

        return market
Ejemplo n.º 2
0
    def fetch_market(self, market_id):
        """
        Fetch and cache it. It rarely changes, except for base exchange rate, so assume it once for all.
        @todo min/max/step/min_notional
        """
        instrument = self.connector.ws.get_instrument(market_id)
        # funds = self.connector.ws.funds()  # to get account base currency (if XBt or XBT)
        xbt_usd = self.connector.ws.get_instrument("XBTUSD")

        if instrument:
            # tickSize is the minimum price increment (0.5USD for XBTUSD)
            tradeable = instrument.get('state', 'Closed') == 'Open'
            update_time = self._parse_datetime(instrument.get('timestamp')).timestamp()
            symbol = instrument.get('symbol', '')
            base_symbol = instrument.get('rootSymbol', '')
            quote_symbol = symbol[-3:]

            # if funds['currency'] == 'XBt':
            #   # XBt to XBT
            #   ratio = 1.0 / 100000000.0

            # if base_symbol == 'USD':
            #   # USD is base then convert to XBT
            #   ratio *= to_base_rate

            bid = instrument.get('bidPrice')
            ofr = instrument.get('askPrice')

            market = Market(market_id, symbol)

            # compute base precision from the tick size, example 0.05 => 2
            base_precision = -math.floor(math.log10(instrument.get('tickSize', 1.0)))

            market.set_base(base_symbol, base_symbol, base_precision)
            market.set_quote(quote_symbol, quote_symbol)

            # base to XBT
            market.base_exchange_rate = 1.0

            # base instrument
            base_market_id = "XBT" + quote_symbol
            base_market = self.connector.ws.get_instrument(base_market_id)
            if base_market_id != symbol and base_market:
                market.base_exchange_rate = base_market.get('lastPrice', 1.0) / instrument.get('lastPrice', 1.0)

            # @todo 'multiplier', 'riskStep', 'riskLimit'

            # limits
            min_notional = 1.0  # $

            if quote_symbol != "USD" and base_market_id != "XBT":
                # any contract on futur XBT quote
                min_notional = 0.0001

            # BCHXBT 'maxOrderQty': 100000000, 'maxPrice': 10, 'lotSize': 1, 'tickSize': 0.0001,
            # XBCUSD 'maxOrderQty': 10000000, 'maxPrice': 1000000, 'lotSize': 1, 'tickSize': 0.5,
            market.set_size_limits(instrument.get('tickSize', 1.0), instrument.get('maxOrderQty', 0.0), instrument.get('tickSize', 1.0))
            market.set_notional_limits(min_notional, instrument.get('maxPrice', 0.0), 0.0)
            market.set_price_limits(0.0, 0.0, instrument.get('tickSize', 1.0))

            # need to divided by account currency XBt = 100000000
            market.margin_factor = instrument.get('initMargin', 1.0)
            # market.max_margin_factor = 1.0 / (instrument.get('riskLimit', 1.0) * ratio) # ex: 20000000000 for max leverage 200

            # '-' if perpetual else match the regexp and keep the expiry part only
            expiry = BitMexWatcher.EXPIRY_RE.match(market_id)

            # or instrument.get(expiry') == '2018-12-28T12:00:00.000Z' for Z18 its 28 of month Z (december) and year 2018
            if expiry is None:
                market.expiry = '-'
            else:
                market.expiry = expiry.group(2) + expiry.group(3)

            market.market_type = Market.TYPE_CRYPTO
            market.unit_type = Market.UNIT_CONTRACTS
            market.contract_type = Market.CONTRACT_CFD  # and FUTUR
            market.trade = Market.TRADE_IND_MARGIN

            if bid is not None and ofr is not None:
                market.bid = bid
                market.ofr = ofr
                market.last_update_time = update_time

            market.lot_size = instrument.get('lotSize', 1.0)  # ex: 1.0 for XBTUSD
            market.contract_size = 1.0
            market.value_per_pip = 1.0
            market.one_pip_means = instrument.get('tickSize', 1.0)

            # contract_size need to be updated as price changes
            # @todo this is wrong... same on update part above
            if quote_symbol == 'USD' and base_market_id == symbol:  # XBTUSD...
                market.contract_size = 1.0 / instrument.get('lastPrice', 1.0)
            elif quote_symbol == 'USD' and base_market_id != symbol:  # ETHUSD...
                market.contract_size = (0.001 * 0.01) * instrument.get('lastPrice', 1.0)
            elif base_market and base_market_id != symbol:  # ADAZ18...
                market.contract_size = 1.0 / instrument.get('lastPrice', 1.0)

            market.value_per_pip = market.contract_size / instrument.get('lastPrice', 1.0)

            market.maker_fee = instrument.get('makerFee', 0.0)
            market.taker_fee = instrument.get('takerFee', 0.0)

            # store the last market info to be used for backtesting
            if not self._read_only:
                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
                    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
                )

            # notify for strategy
            self.service.notify(Signal.SIGNAL_MARKET_INFO_DATA, self.name, (market_id, market))

        return market
Ejemplo n.º 3
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
Ejemplo n.º 4
0
    def fetch_market(self, market_id):
        """
        Fetch and cache it. It rarely changes.
        """
        symbol = self._symbols_data.get(market_id)
        ticker = self._tickers_data.get(market_id)
        account = self._acount_data

        market = None

        if symbol and ticker and account:
            market = Market(symbol['symbol'], symbol['symbol'])

            market.is_open = symbol['status'] == "TRADING"
            market.expiry = '-'

            base_asset = symbol['baseAsset']
            market.set_base(base_asset, base_asset,
                            symbol['baseAssetPrecision'])

            quote_asset = symbol['quoteAsset']
            market.set_quote(quote_asset,
                             symbol.get('quoteAssetUnit', quote_asset),
                             symbol['quotePrecision'])

            # tick size at the base asset precision
            market.one_pip_means = math.pow(10.0,
                                            -symbol['baseAssetPrecision'])
            market.value_per_pip = 1.0
            market.contract_size = 1.0
            market.lot_size = 1.0

            # @todo add margin support
            market.margin_factor = 1.0

            size_limits = ["1.0", "0.0", "1.0"]
            notional_limits = ["1.0", "0.0", "0.0"]
            price_limits = ["0.0", "0.0", "0.0"]

            # size min/max/step
            for afilter in symbol["filters"]:
                if afilter['filterType'] == "LOT_SIZE":
                    size_limits = [
                        afilter['minQty'], afilter['maxQty'],
                        afilter['stepSize']
                    ]

                elif afilter['filterType'] == "MIN_NOTIONAL":
                    notional_limits[0] = afilter['minNotional']

                elif afilter['filterType'] == "PRICE_FILTER":
                    price_limits = [
                        afilter['minPrice'], afilter['maxPrice'],
                        afilter['tickSize']
                    ]

            market.set_size_limits(float(size_limits[0]),
                                   float(size_limits[1]),
                                   float(size_limits[2]))
            market.set_price_limits(float(price_limits[0]),
                                    float(price_limits[1]),
                                    float(price_limits[2]))
            market.set_notional_limits(float(notional_limits[0]), 0.0, 0.0)

            market.unit_type = Market.UNIT_AMOUNT
            market.market_type = Market.TYPE_CRYPTO
            market.contract_type = Market.CONTRACT_SPOT

            market.trade = 0
            if symbol.get('isSpotTradingAllowed', False):
                market.trade |= Market.TRADE_ASSET
            if symbol.get('isMarginTradingAllowed', False):
                market.trade |= Market.TRADE_IND_MARGIN

            # @todo orders capacities
            # symbol['orderTypes'] in ['LIMIT', 'LIMIT_MAKER', 'MARKET', 'STOP_LOSS_LIMIT', 'TAKE_PROFIT_LIMIT']
            # market.orders =

            if symbol.get('ocoAllowed', False):
                market.orders |= Market.ORDER_ONE_CANCEL_OTHER

            market.maker_fee = account['makerCommission'] * 0.0001
            market.taker_fee = account['takerCommission'] * 0.0001

            # market.buyer_commission = account['buyerCommission']
            # market.seller_commission = account['sellerCommission']

            # only order book can give us bid/ofr
            market.bid = float(ticker['price'])
            market.ofr = float(ticker['price'])

            mid_price = float(ticker['price'])

            if quote_asset != self.BASE_QUOTE:
                if self._tickers_data.get(quote_asset + self.BASE_QUOTE):
                    market.base_exchange_rate = float(
                        self._tickers_data.get(quote_asset + self.BASE_QUOTE,
                                               {'price', '1.0'})['price'])
                elif self._tickers_data.get(self.BASE_QUOTE + quote_asset):
                    market.base_exchange_rate = 1.0 / float(
                        self._tickers_data.get(self.BASE_QUOTE + quote_asset,
                                               {'price', '1.0'})['price'])
                else:
                    market.base_exchange_rate = 1.0
            else:
                market.base_exchange_rate = 1.0

            market.contract_size = 1.0 / mid_price
            market.value_per_pip = market.contract_size / mid_price

            # volume 24h

            # in client.get_ticker but cost is 40 for any symbols then wait it at all-tickets WS event
            # vol24_base = ticker24h('volume')
            # vol24_quote = ticker24h('quoteVolume')

            # notify for strategy
            self.service.notify(Signal.SIGNAL_MARKET_INFO_DATA, self.name,
                                (market_id, market))

            # store the last market info to be used for backtesting
            if not self._read_only:
                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),
                    '-',
                    *size_limits,
                    *notional_limits,
                    *price_limits,
                    str(market.maker_fee),
                    str(market.taker_fee),
                    str(market.maker_commission),
                    str(market.taker_commission)))

        return market
Ejemplo n.º 5
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
                                          )
Ejemplo n.º 6
0
    def fetch_market(self, market_id):
        """
        Fetch and cache it. It rarely changes.
        """
        instrument = self._instruments.get(market_id)

        market = None

        if instrument:
            market = Market(market_id, instrument['altname'])

            market.is_open = True
            market.expiry = '-'

            # "wsname":"XBT\/USD"
            # wsname = WebSocket pair name (if available)
            # pair_decimals = scaling decimal places for pair
            # lot_decimals = scaling decimal places for volume
            # lot_multiplier = amount to multiply lot volume by to get currency volume

            # "aclass_base":"currency"
            base_asset = instrument['base']  # XXBT
            market.set_base(base_asset, base_asset,
                            instrument['pair_decimals'])

            # "aclass_quote":"currency"
            quote_asset = instrument['quote']  # ZUSD
            market.set_quote(quote_asset, quote_asset,
                             instrument['lot_decimals'])  # 8

            # tick size at the base asset precision
            market.one_pip_means = math.pow(10.0,
                                            -instrument['pair_decimals'])  # 1
            market.value_per_pip = 1.0
            market.contract_size = 1.0
            market.lot_size = 1.0  # "lot":"unit", "lot_multiplier":1

            # "margin_call":80, "margin_stop":40
            # margin_call = margin call level
            # margin_stop = stop-out/liquidation margin level

            leverages = set(instrument.get('leverage_buy', []))
            leverages.intersection(set(instrument.get('leverage_sell', [])))

            market.margin_factor = 1.0 / max(leverages) if len(
                leverages) > 0 else 1.0

            market.set_leverages(leverages)

            size_limit = self._size_limits.get(instrument['altname'], {})
            min_size = size_limit.get('min-size', 1.0)

            size_limits = [str(min_size), "0.0", str(min_size)]
            notional_limits = ["0.0", "0.0", "0.0"]
            price_limits = ["0.0", "0.0", "0.0"]

            market.set_size_limits(float(size_limits[0]),
                                   float(size_limits[1]),
                                   float(size_limits[2]))
            market.set_price_limits(float(price_limits[0]),
                                    float(price_limits[1]),
                                    float(price_limits[2]))
            market.set_notional_limits(float(notional_limits[0]), 0.0, 0.0)

            # "lot":"unit"
            market.unit_type = Market.UNIT_AMOUNT
            market.market_type = Market.TYPE_CRYPTO
            market.contract_type = Market.CONTRACT_SPOT

            market.trade = Market.TRADE_ASSET
            if leverages:
                market.trade |= Market.TRADE_MARGIN
                market.trade |= Market.TRADE_FIFO

            # orders capacities
            market.orders = Order.ORDER_LIMIT | Order.ORDER_MARKET | Order.ORDER_STOP | Order.ORDER_TAKE_PROFIT

            # @todo take the first but it might depends of the traded volume per 30 days, then request volume window to got it
            # "fees":[[0,0.26],[50000,0.24],[100000,0.22],[250000,0.2],[500000,0.18],[1000000,0.16],[2500000,0.14],[5000000,0.12],[10000000,0.1]],
            # "fees_maker":[[0,0.16],[50000,0.14],[100000,0.12],[250000,0.1],[500000,0.08],[1000000,0.06],[2500000,0.04],[5000000,0.02],[10000000,0]],
            fees = instrument.get('fees', [])
            fees_maker = instrument.get('fees_maker', [])

            if fees:
                market.taker_fee = round(fees[0][1] * 0.01, 6)
            if fees_maker:
                market.maker_fee = round(fees_maker[0][1] * 0.01, 6)

            if instrument.get('fee_volume_currency'):
                market.fee_currency = instrument['fee_volume_currency']

            if quote_asset != self.BASE_QUOTE:
                # from XXBTZUSD / XXBTZEUR ...
                # @todo
                pass
                # if self._tickers_data.get(quote_asset+self.BASE_QUOTE):
                #     market.base_exchange_rate = float(self._tickers_data.get(quote_asset+self.BASE_QUOTE, {'price', '1.0'})['price'])
                # elif self._tickers_data.get(self.BASE_QUOTE+quote_asset):
                #     market.base_exchange_rate = 1.0 / float(self._tickers_data.get(self.BASE_QUOTE+quote_asset, {'price', '1.0'})['price'])
                # else:
                #     market.base_exchange_rate = 1.0
            else:
                market.base_exchange_rate = 1.0

            # @todo contract_size
            # market.contract_size = 1.0 / mid_price
            # market.value_per_pip = market.contract_size / mid_price

            # volume 24h : not have here

            # notify for strategy
            self.service.notify(Signal.SIGNAL_MARKET_INFO_DATA, self.name,
                                (market_id, market))

            # store the last market info to be used for backtesting
            if not self._read_only:
                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),
                    '-',
                    *size_limits,
                    *notional_limits,
                    *price_limits,
                    str(market.maker_fee),
                    str(market.taker_fee),
                    str(market.maker_commission),
                    str(market.taker_commission)))

        return market
Ejemplo n.º 7
0
    def fetch_market(self, market_id):
        """
        Fetch and cache it. It rarely changes.
        """
        instrument = self._instruments.get(market_id)

        market = None

        if instrument:
            market = Market(market_id, instrument['altname'])

            market.is_open = True
            market.expiry = '-'

            # "wsname":"XBT\/USD"
            # wsname = WebSocket pair name (if available)
            # pair_decimals = scaling decimal places for pair
            # lot_decimals = scaling decimal places for volume
            # lot_multiplier = amount to multiply lot volume by to get currency volume

            # "aclass_base":"currency"
            base_asset = instrument['base']  # XXBT
            market.set_base(base_asset, base_asset,
                            instrument['pair_decimals'])

            # "aclass_quote":"currency"
            quote_asset = instrument['quote']  # ZUSD
            market.set_quote(quote_asset, quote_asset,
                             instrument['lot_decimals'])  # 8

            # tick size at the base asset precision
            market.one_pip_means = math.pow(10.0,
                                            -instrument['pair_decimals'])  # 1
            market.value_per_pip = 1.0
            market.contract_size = 1.0
            market.lot_size = 1.0  # "lot":"unit", "lot_multiplier":1

            # "margin_call":80, "margin_stop":40
            # margin_call = margin call level
            # margin_stop = stop-out/liquidation margin level

            leverages = set(instrument.get('leverage_buy', []))
            leverages.intersection(set(instrument.get('leverage_sell', [])))

            market.margin_factor = 1.0 / max(leverages)

            market.set_leverages(leverages)

            size_limits = ["1.0", "0.0", "1.0"]
            notional_limits = ["1.0", "0.0", "0.0"]
            price_limits = ["0.0", "0.0", "0.0"]

            # size min/max/step @todo using lot_decimals / pair_decimals
            # for afilter in instrument["filters"]:
            #     if afilter['filterType'] == "LOT_SIZE":
            #         size_limits = [afilter['minQty'], afilter['maxQty'], afilter['stepSize']]

            #     elif afilter['filterType'] == "MIN_NOTIONAL":
            #         notional_limits[0] = afilter['minNotional']

            #     elif afilter['filterType'] == "PRICE_FILTER":
            #         price_limits = [afilter['minPrice'], afilter['maxPrice'], afilter['tickSize']]

            # if float(size_limits[2]) < 1:
            #     size_limits[2] = str(float(size_limits[2]))  # * 10)

            market.set_size_limits(float(size_limits[0]),
                                   float(size_limits[1]),
                                   float(size_limits[2]))
            market.set_price_limits(float(price_limits[0]),
                                    float(price_limits[1]),
                                    float(price_limits[2]))
            market.set_notional_limits(float(notional_limits[0]), 0.0, 0.0)

            # "lot":"unit"
            market.unit_type = Market.UNIT_AMOUNT
            market.market_type = Market.TYPE_CRYPTO
            market.trade = Market.TRADE_ASSET
            market.contract_type = Market.CONTRACT_SPOT

            # @todo add a copy with
            market.trade = Market.TRADE_MARGIN
            market.contract_type = Market.CONTRACT_FUTUR

            # orders capacities
            market.orders = Order.ORDER_LIMIT | Order.ORDER_MARKET | Order.ORDER_STOP | Order.ORDER_TAKE_PROFIT

            # "fees":[[0,0.26],[50000,0.24],[100000,0.22],[250000,0.2],[500000,0.18],[1000000,0.16],[2500000,0.14],[5000000,0.12],[10000000,0.1]],
            # "fees_maker":[[0,0.16],[50000,0.14],[100000,0.12],[250000,0.1],[500000,0.08],[1000000,0.06],[2500000,0.04],[5000000,0.02],[10000000,0]],

            # market.maker_fee = account['makerCommission'] * 0.0001
            # market.taker_fee = account['takerCommission'] * 0.0001

            # 'fee_volume_currency': 'ZUSD'
            # fee_volume_currency = volume discount currency

            # if quote_asset != self.BASE_QUOTE:
            #     if self._tickers_data.get(quote_asset+self.BASE_QUOTE):
            #         market.base_exchange_rate = float(self._tickers_data.get(quote_asset+self.BASE_QUOTE, {'price', '1.0'})['price'])
            #     elif self._tickers_data.get(self.BASE_QUOTE+quote_asset):
            #         market.base_exchange_rate = 1.0 / float(self._tickers_data.get(self.BASE_QUOTE+quote_asset, {'price', '1.0'})['price'])
            #     else:
            #         market.base_exchange_rate = 1.0
            # else:
            #     market.base_exchange_rate = 1.0

            # market.contract_size = 1.0 / mid_price
            # market.value_per_pip = market.contract_size / mid_price

            # volume 24h : not have here

            # store the last market info to be used for backtesting
            if not self._read_only:
                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),
                    '-',
                    *size_limits,
                    *notional_limits,
                    *price_limits,
                    str(market.maker_fee),
                    str(market.taker_fee),
                    str(market.maker_commission),
                    str(market.taker_commission)))

            # notify for strategy
            self.service.notify(Signal.SIGNAL_MARKET_INFO_DATA, self.name,
                                (market_id, market))

        return market