@@ -9,12 +9,13 @@ from freqtrade.exchange.bitpanda import Bitpanda
|
||||
from freqtrade.exchange.bittrex import Bittrex
|
||||
from freqtrade.exchange.bybit import Bybit
|
||||
from freqtrade.exchange.coinbasepro import Coinbasepro
|
||||
from freqtrade.exchange.exchange import (available_exchanges, ccxt_exchanges,
|
||||
is_exchange_known_ccxt, is_exchange_officially_supported,
|
||||
market_is_active, timeframe_to_minutes, timeframe_to_msecs,
|
||||
timeframe_to_next_date, timeframe_to_prev_date,
|
||||
timeframe_to_seconds, validate_exchange,
|
||||
validate_exchanges)
|
||||
from freqtrade.exchange.exchange import (amount_to_precision, available_exchanges, ccxt_exchanges,
|
||||
date_minus_candles, is_exchange_known_ccxt,
|
||||
is_exchange_officially_supported, market_is_active,
|
||||
price_to_precision, timeframe_to_minutes,
|
||||
timeframe_to_msecs, timeframe_to_next_date,
|
||||
timeframe_to_prev_date, timeframe_to_seconds,
|
||||
validate_exchange, validate_exchanges)
|
||||
from freqtrade.exchange.ftx import Ftx
|
||||
from freqtrade.exchange.gateio import Gateio
|
||||
from freqtrade.exchange.hitbtc import Hitbtc
|
||||
|
@@ -681,45 +681,35 @@ class Exchange:
|
||||
"""
|
||||
return endpoint in self._api.has and self._api.has[endpoint]
|
||||
|
||||
def get_precision_amount(self, pair: str) -> Optional[float]:
|
||||
"""
|
||||
Returns the amount precision of the exchange.
|
||||
:param pair: Pair to get precision for
|
||||
:return: precision for amount or None. Must be used in combination with precisionMode
|
||||
"""
|
||||
return self.markets.get(pair, {}).get('precision', {}).get('amount', None)
|
||||
|
||||
def get_precision_price(self, pair: str) -> Optional[float]:
|
||||
"""
|
||||
Returns the price precision of the exchange.
|
||||
:param pair: Pair to get precision for
|
||||
:return: precision for price or None. Must be used in combination with precisionMode
|
||||
"""
|
||||
return self.markets.get(pair, {}).get('precision', {}).get('price', None)
|
||||
|
||||
def amount_to_precision(self, pair: str, amount: float) -> float:
|
||||
"""
|
||||
Returns the amount to buy or sell to a precision the Exchange accepts
|
||||
Re-implementation of ccxt internal methods - ensuring we can test the result is correct
|
||||
based on our definitions.
|
||||
"""
|
||||
if self.markets[pair]['precision']['amount'] is not None:
|
||||
amount = float(decimal_to_precision(amount, rounding_mode=TRUNCATE,
|
||||
precision=self.markets[pair]['precision']['amount'],
|
||||
counting_mode=self.precisionMode,
|
||||
))
|
||||
|
||||
return amount
|
||||
"""
|
||||
return amount_to_precision(amount, self.get_precision_amount(pair), self.precisionMode)
|
||||
|
||||
def price_to_precision(self, pair: str, price: float) -> float:
|
||||
"""
|
||||
Returns the price rounded up to the precision the Exchange accepts.
|
||||
Partial Re-implementation of ccxt internal method decimal_to_precision(),
|
||||
which does not support rounding up
|
||||
TODO: If ccxt supports ROUND_UP for decimal_to_precision(), we could remove this and
|
||||
align with amount_to_precision().
|
||||
Rounds up
|
||||
"""
|
||||
if self.markets[pair]['precision']['price']:
|
||||
# price = float(decimal_to_precision(price, rounding_mode=ROUND,
|
||||
# precision=self.markets[pair]['precision']['price'],
|
||||
# counting_mode=self.precisionMode,
|
||||
# ))
|
||||
if self.precisionMode == TICK_SIZE:
|
||||
precision = FtPrecise(self.markets[pair]['precision']['price'])
|
||||
price_str = FtPrecise(price)
|
||||
missing = price_str % precision
|
||||
if not missing == FtPrecise("0"):
|
||||
price = round(float(str(price_str - missing + precision)), 14)
|
||||
else:
|
||||
symbol_prec = self.markets[pair]['precision']['price']
|
||||
big_price = price * pow(10, symbol_prec)
|
||||
price = ceil(big_price) / pow(10, symbol_prec)
|
||||
return price
|
||||
return price_to_precision(price, self.get_precision_price(pair), self.precisionMode)
|
||||
|
||||
def price_get_one_pip(self, pair: str, price: float) -> float:
|
||||
"""
|
||||
@@ -2862,3 +2852,61 @@ def market_is_active(market: Dict) -> bool:
|
||||
# See https://github.com/ccxt/ccxt/issues/4874,
|
||||
# https://github.com/ccxt/ccxt/issues/4075#issuecomment-434760520
|
||||
return market.get('active', True) is not False
|
||||
|
||||
|
||||
def amount_to_precision(amount: float, amount_precision: Optional[float],
|
||||
precisionMode: Optional[int]) -> float:
|
||||
"""
|
||||
Returns the amount to buy or sell to a precision the Exchange accepts
|
||||
Re-implementation of ccxt internal methods - ensuring we can test the result is correct
|
||||
based on our definitions.
|
||||
:param amount: amount to truncate
|
||||
:param amount_precision: amount precision to use.
|
||||
should be retrieved from markets[pair]['precision']['amount']
|
||||
:param precisionMode: precision mode to use. Should be used from precisionMode
|
||||
one of ccxt's DECIMAL_PLACES, SIGNIFICANT_DIGITS, or TICK_SIZE
|
||||
:return: truncated amount
|
||||
"""
|
||||
if amount_precision is not None and precisionMode is not None:
|
||||
precision = int(amount_precision) if precisionMode != TICK_SIZE else amount_precision
|
||||
# precision must be an int for non-ticksize inputs.
|
||||
amount = float(decimal_to_precision(amount, rounding_mode=TRUNCATE,
|
||||
precision=precision,
|
||||
counting_mode=precisionMode,
|
||||
))
|
||||
|
||||
return amount
|
||||
|
||||
|
||||
def price_to_precision(price: float, price_precision: Optional[float],
|
||||
precisionMode: Optional[int]) -> float:
|
||||
"""
|
||||
Returns the price rounded up to the precision the Exchange accepts.
|
||||
Partial Re-implementation of ccxt internal method decimal_to_precision(),
|
||||
which does not support rounding up
|
||||
TODO: If ccxt supports ROUND_UP for decimal_to_precision(), we could remove this and
|
||||
align with amount_to_precision().
|
||||
!!! Rounds up
|
||||
:param price: price to convert
|
||||
:param price_precision: price precision to use. Used from markets[pair]['precision']['price']
|
||||
:param precisionMode: precision mode to use. Should be used from precisionMode
|
||||
one of ccxt's DECIMAL_PLACES, SIGNIFICANT_DIGITS, or TICK_SIZE
|
||||
:return: price rounded up to the precision the Exchange accepts
|
||||
|
||||
"""
|
||||
if price_precision is not None and precisionMode is not None:
|
||||
# price = float(decimal_to_precision(price, rounding_mode=ROUND,
|
||||
# precision=price_precision,
|
||||
# counting_mode=self.precisionMode,
|
||||
# ))
|
||||
if precisionMode == TICK_SIZE:
|
||||
precision = FtPrecise(price_precision)
|
||||
price_str = FtPrecise(price)
|
||||
missing = price_str % precision
|
||||
if not missing == FtPrecise("0"):
|
||||
price = round(float(str(price_str - missing + precision)), 14)
|
||||
else:
|
||||
symbol_prec = price_precision
|
||||
big_price = price * pow(10, symbol_prec)
|
||||
price = ceil(big_price) / pow(10, symbol_prec)
|
||||
return price
|
||||
|
@@ -7,9 +7,8 @@ from freqtrade.constants import BuySell
|
||||
from freqtrade.enums import MarginMode, TradingMode
|
||||
from freqtrade.enums.candletype import CandleType
|
||||
from freqtrade.exceptions import DDosProtection, OperationalException, TemporaryError
|
||||
from freqtrade.exchange import Exchange
|
||||
from freqtrade.exchange import Exchange, date_minus_candles
|
||||
from freqtrade.exchange.common import retrier
|
||||
from freqtrade.exchange.exchange import date_minus_candles
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
Reference in New Issue
Block a user