def adjust_price(self, price, use_quote=True): """ Format the price according to the precision. @param use_quote True use quote display or quote, False base, None no symbol only price. """ if use_quote: precision = self._price_limits[ 3] or self._quote_precision # uses tick price if defined else quote precision else: precision = self._base_precision if not precision: if use_quote: # quote use value per pip precision = decimal_place(self.value_per_pip) else: # base use one pip mean alias tick size precision = decimal_place(self.one_pip_means) if not precision: precision = 8 tick_size = self._price_limits[2] or self.one_pip_means # adjusted price at precision and by step of pip meaning return truncate(round(price / tick_size) * tick_size, precision)
def format_spread(self, spread, shifted=False): """ Format the spread according to the precision. @param shifted Shift the spread value by power of 10 based on the tick size. """ precision = self._price_limits[3] or self._quote_precision if not precision: if use_quote: # quote use value per pip precision = decimal_place(self.value_per_pip) else: # base use one pip mean alias tick size precision = decimal_place(self.one_pip_means) if not precision: precision = 8 tick_size = self._price_limits[2] or self.one_pip_means # adjusted spread at precision and by step of pip meaning # adjusted_price = truncate(round(spread / tick_size) * tick_size, precision) if shifted: adjusted_spread = spread * 10**precision else: adjusted_spread = spread formatted_spread = "{:0.0{}f}".format(adjusted_spread, precision) # remove tailing 0s and dot if '.' in formatted_spread: formatted_spread = formatted_spread.rstrip('0').rstrip('.') return formatted_spread
def format_price(self, price, use_quote=True, display_symbol=False): """ Format the price according to the precision. @param use_quote True use quote display or quote, False base, None no symbol only price. """ if use_quote: precision = self._price_limits[ 3] or self._quote_precision # uses tick price if defined else quote precision else: precision = self._base_precision if not precision: if use_quote: # quote use value per pip precision = decimal_place(self.value_per_pip) else: # base use one pip mean alias tick size precision = decimal_place(self.one_pip_means) if not precision: precision = 8 tick_size = self._price_limits[2] or self.one_pip_means # adjusted price at precision and by step of pip meaning # adjusted_price = truncate(int(truncate(price, precision) / tick_size) * tick_size, precision) adjusted_price = truncate( round(price / tick_size) * tick_size, precision) formatted_price = "{:0.0{}f}".format(adjusted_price, precision) # remove tailing 0s and dot if '.' in formatted_price: formatted_price = formatted_price.rstrip('0').rstrip('.') if not display_symbol: return formatted_price if use_quote: return "%s%s" % (formatted_price, self._quote_display or self._quote) else: return "%s%s" % (formatted_price, self._base_display or self._base)
def adjust_price(self, price): """ Format the price according to the precision. @param use_quote True use quote display or quote, False base, None no symbol only price. """ precision = self._price_limits[3] or self._quote_precision if not precision: precision = decimal_place(self.value_per_pip) or 8 tick_size = self._price_limits[2] or self.one_pip_means # adjusted price at precision and by step of pip meaning return truncate(round(price / tick_size) * tick_size, precision)
def format_base_price(self, price): """ Format the base price according to its precision. """ precision = self._base_precision if not precision: precision = decimal_place(self.one_pip_means) or 8 tick_size = self.one_pip_means or 1.0 adjusted_price = truncate( round(price / tick_size) * tick_size, precision) formatted_price = "{:0.0{}f}".format(adjusted_price, precision) # remove tailing 0s and dot if '.' in formatted_price: formatted_price = formatted_price.rstrip('0').rstrip('.') return formatted_price
def format_price(self, price): """ Format the price according to its precision. """ precision = self._price_limits[3] or self._quote_precision if not precision: precision = decimal_place(self.value_per_pip) or 8 tick_size = self._price_limits[2] or self.one_pip_means # adjusted price at precision and by step of tick size adjusted_price = truncate( round(price / tick_size) * tick_size, precision) formatted_price = "{:0.0{}f}".format(adjusted_price, precision) # remove tailing 0s and dot if '.' in formatted_price: formatted_price = formatted_price.rstrip('0').rstrip('.') return formatted_price
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
def set_price_limits(self, min_price, max_price, step_price): price_precision = max( 0, decimal_place(step_price) if step_price > 0 else 0) self._price_limits = (min_price, max_price, step_price, price_precision)
def set_notional_limits(self, min_notional, max_notional, step_notional): notional_precision = max( 0, decimal_place(step_notional) if step_notional > 0 else 0) self._notional_limits = (min_notional, max_notional, step_notional, notional_precision)
def set_size_limits(self, min_size, max_size, step_size): size_precision = max(0, decimal_place(step_size) if step_size > 0 else 0) self._size_limits = (min_size, max_size, step_size, size_precision)