Update more to use candleType

This commit is contained in:
Matthias 2021-12-03 14:11:24 +01:00
parent 5493212672
commit 2f17fa2765
18 changed files with 56 additions and 55 deletions

View File

@ -11,7 +11,7 @@ import pandas as pd
from pandas import DataFrame, to_datetime
from freqtrade.constants import DEFAULT_DATAFRAME_COLUMNS, DEFAULT_TRADES_COLUMNS, TradeList
from freqtrade.enums.candletype import CandleType
from freqtrade.enums import CandleType
logger = logging.getLogger(__name__)

View File

@ -13,8 +13,7 @@ from pandas import DataFrame
from freqtrade.configuration import TimeRange
from freqtrade.constants import ListPairsWithTimeframes, PairWithTimeframe
from freqtrade.data.history import load_pair_history
from freqtrade.enums import RunMode
from freqtrade.enums.candletype import CandleType
from freqtrade.enums import CandleType, RunMode
from freqtrade.exceptions import ExchangeError, OperationalException
from freqtrade.exchange import Exchange, timeframe_to_seconds
@ -223,7 +222,7 @@ class DataProvider:
raise OperationalException(NO_EXCHANGE_EXCEPTION)
if self.runmode in (RunMode.DRY_RUN, RunMode.LIVE):
return self._exchange.klines(
(pair, timeframe or self._config['timeframe'], candle_type),
(pair, timeframe or self._config['timeframe'], CandleType.from_string(candle_type)),
copy=copy
)
else:

View File

@ -9,7 +9,7 @@ import pandas as pd
from freqtrade.configuration import TimeRange
from freqtrade.constants import (DEFAULT_DATAFRAME_COLUMNS, DEFAULT_TRADES_COLUMNS,
ListPairsWithTimeframes, TradeList)
from freqtrade.enums.candletype import CandleType
from freqtrade.enums import CandleType
from .idatahandler import IDataHandler

View File

@ -12,7 +12,7 @@ from freqtrade.constants import DEFAULT_DATAFRAME_COLUMNS
from freqtrade.data.converter import (clean_ohlcv_dataframe, ohlcv_to_dataframe,
trades_remove_duplicates, trades_to_ohlcv)
from freqtrade.data.history.idatahandler import IDataHandler, get_datahandler
from freqtrade.enums.candletype import CandleType
from freqtrade.enums import CandleType
from freqtrade.exceptions import OperationalException
from freqtrade.exchange import Exchange
from freqtrade.misc import format_ms_time

View File

@ -17,7 +17,7 @@ from freqtrade import misc
from freqtrade.configuration import TimeRange
from freqtrade.constants import ListPairsWithTimeframes, TradeList
from freqtrade.data.converter import clean_ohlcv_dataframe, trades_remove_duplicates, trim_dataframe
from freqtrade.enums.candletype import CandleType
from freqtrade.enums import CandleType
from freqtrade.exchange import timeframe_to_seconds

View File

@ -10,7 +10,7 @@ from freqtrade import misc
from freqtrade.configuration import TimeRange
from freqtrade.constants import DEFAULT_DATAFRAME_COLUMNS, ListPairsWithTimeframes, TradeList
from freqtrade.data.converter import trades_dict_to_list
from freqtrade.enums.candletype import CandleType
from freqtrade.enums import CandleType
from .idatahandler import IDataHandler

View File

@ -8,7 +8,7 @@ from typing import Dict, List, Optional, Tuple
import arrow
import ccxt
from freqtrade.enums import Collateral, TradingMode
from freqtrade.enums import CandleType, Collateral, TradingMode
from freqtrade.exceptions import (DDosProtection, InsufficientFundsError, InvalidOrderException,
OperationalException, TemporaryError)
from freqtrade.exchange import Exchange
@ -197,14 +197,13 @@ class Binance(Exchange):
raise OperationalException(e) from e
async def _async_get_historic_ohlcv(self, pair: str, timeframe: str,
since_ms: int, is_new_pair: bool = False,
raise_: bool = False,
candle_type: str = ''
since_ms: int, candle_type: CandleType,
is_new_pair: bool = False, raise_: bool = False,
) -> Tuple[str, str, str, List]:
"""
Overwrite to introduce "fast new pair" functionality by detecting the pair's listing date
Does not work for other exchanges, which don't return the earliest data when called with "0"
:param candle_type: '', mark, index, premiumIndex, or funding_rate
:param candle_type: Any of the enum CandleType (must match trading mode!)
"""
if is_new_pair:
x = await self._async_get_candle_history(pair, timeframe, 0, candle_type)

View File

@ -20,9 +20,9 @@ from ccxt.base.decimal_to_precision import (ROUND_DOWN, ROUND_UP, TICK_SIZE, TRU
from pandas import DataFrame
from freqtrade.constants import (DEFAULT_AMOUNT_RESERVE_PERCENT, NON_OPEN_EXCHANGE_STATES,
ListPairsWithTimeframes)
ListPairsWithTimeframes, PairWithTimeframe)
from freqtrade.data.converter import ohlcv_to_dataframe, trades_dict_to_list
from freqtrade.enums import Collateral, TradingMode
from freqtrade.enums import CandleType, Collateral, TradingMode
from freqtrade.exceptions import (DDosProtection, ExchangeError, InsufficientFundsError,
InvalidOrderException, OperationalException, PricingError,
RetryableOrderError, TemporaryError)
@ -92,7 +92,7 @@ class Exchange:
self._config.update(config)
# Holds last candle refreshed time of each pair
self._pairs_last_refresh_time: Dict[Tuple[str, str, str], int] = {}
self._pairs_last_refresh_time: Dict[PairWithTimeframe, int] = {}
# Timestamp of last markets refresh
self._last_markets_refresh: int = 0
@ -105,7 +105,7 @@ class Exchange:
self._buy_rate_cache: TTLCache = TTLCache(maxsize=100, ttl=1800)
# Holds candles
self._klines: Dict[Tuple[str, str, str], DataFrame] = {}
self._klines: Dict[PairWithTimeframe, DataFrame] = {}
# Holds all open sell orders for dry_run
self._dry_run_open_orders: Dict[str, Any] = {}
@ -359,7 +359,7 @@ class Exchange:
or (self.trading_mode == TradingMode.FUTURES and self.market_is_future(market))
)
def klines(self, pair_interval: Tuple[str, str, str], copy: bool = True) -> DataFrame:
def klines(self, pair_interval: PairWithTimeframe, copy: bool = True) -> DataFrame:
if pair_interval in self._klines:
return self._klines[pair_interval].copy() if copy else self._klines[pair_interval]
else:
@ -1314,8 +1314,8 @@ class Exchange:
# Historic data
def get_historic_ohlcv(self, pair: str, timeframe: str,
since_ms: int, is_new_pair: bool = False,
candle_type: str = '') -> List:
since_ms: int, candle_type: CandleType,
is_new_pair: bool = False) -> List:
"""
Get candle history using asyncio and returns the list of candles.
Handles all async work for this.
@ -1327,7 +1327,7 @@ class Exchange:
:return: List with candle (OHLCV) data
"""
data: List
pair, timeframe, candle_type, data = asyncio.get_event_loop().run_until_complete(
pair, _, _, data = asyncio.get_event_loop().run_until_complete(
self._async_get_historic_ohlcv(pair=pair, timeframe=timeframe,
since_ms=since_ms, is_new_pair=is_new_pair,
candle_type=candle_type))
@ -1335,13 +1335,13 @@ class Exchange:
return data
def get_historic_ohlcv_as_df(self, pair: str, timeframe: str,
since_ms: int, candle_type: str = '') -> DataFrame:
since_ms: int, candle_type: CandleType) -> DataFrame:
"""
Minimal wrapper around get_historic_ohlcv - converting the result into a dataframe
:param pair: Pair to download
:param timeframe: Timeframe to get data for
:param since_ms: Timestamp in milliseconds to get history from
:param candle_type: '', mark, index, premiumIndex, or funding_rate
:param candle_type: Any of the enum CandleType (must match trading mode!)
:return: OHLCV DataFrame
"""
ticks = self.get_historic_ohlcv(pair, timeframe, since_ms=since_ms, candle_type=candle_type)
@ -1349,14 +1349,13 @@ class Exchange:
drop_incomplete=self._ohlcv_partial_candle)
async def _async_get_historic_ohlcv(self, pair: str, timeframe: str,
since_ms: int, is_new_pair: bool = False,
raise_: bool = False,
candle_type: str = ''
since_ms: int, candle_type: CandleType,
is_new_pair: bool = False, raise_: bool = False,
) -> Tuple[str, str, str, List]:
"""
Download historic ohlcv
:param is_new_pair: used by binance subclass to allow "fast" new pair downloading
:param candle_type: '', mark, index, premiumIndex, or funding_rate
:param candle_type: Any of the enum CandleType (must match trading mode!)
"""
one_call = timeframe_to_msecs(timeframe) * self.ohlcv_candle_limit(timeframe)
@ -1391,8 +1390,8 @@ class Exchange:
def refresh_latest_ohlcv(self, pair_list: ListPairsWithTimeframes, *,
since_ms: Optional[int] = None, cache: bool = True,
candle_type: str = ''
) -> Dict[Tuple[str, str, str], DataFrame]:
candle_type: CandleType = CandleType.SPOT_
) -> Dict[PairWithTimeframe, DataFrame]:
"""
Refresh in-memory OHLCV asynchronously and set `_klines` with the result
Loops asynchronously over pair_list and downloads all pairs async (semi-parallel).
@ -1410,7 +1409,7 @@ class Exchange:
# Gather coroutines to run
for pair, timeframe, candle_type in set(pair_list):
if ((pair, timeframe, candle_type) not in self._klines or not cache
or self._now_is_time_to_refresh(pair, timeframe)):
or self._now_is_time_to_refresh(pair, timeframe, candle_type)):
if not since_ms and self.required_candle_call_count > 1:
# Multiple calls for one pair - to get more history
one_call = timeframe_to_msecs(timeframe) * self.ohlcv_candle_limit(timeframe)
@ -1463,12 +1462,7 @@ class Exchange:
return results_df
def _now_is_time_to_refresh(
self,
pair: str,
timeframe: str,
candle_type: str = ''
) -> bool:
def _now_is_time_to_refresh(self, pair: str, timeframe: str, candle_type: CandleType) -> bool:
# Timeframe in seconds
interval_in_sec = timeframe_to_seconds(timeframe)

View File

@ -17,9 +17,7 @@ from freqtrade.data import history
from freqtrade.data.btanalysis import trade_list_to_dataframe
from freqtrade.data.converter import trim_dataframe, trim_dataframes
from freqtrade.data.dataprovider import DataProvider
from freqtrade.enums import BacktestState, SellType
from freqtrade.enums.candletype import CandleType
from freqtrade.enums.tradingmode import TradingMode
from freqtrade.enums import BacktestState, CandleType, SellType, TradingMode
from freqtrade.exceptions import DependencyException, OperationalException
from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds
from freqtrade.mixins import LoggingMixin

View File

@ -9,6 +9,7 @@ import arrow
from pandas import DataFrame
from freqtrade.configuration import PeriodicCache
from freqtrade.enums import CandleType
from freqtrade.exceptions import OperationalException
from freqtrade.misc import plural
from freqtrade.plugins.pairlist.IPairList import IPairList
@ -72,7 +73,7 @@ class AgeFilter(IPairList):
:return: new allowlist
"""
needed_pairs = [
(p, '1d', '') for p in pairlist
(p, '1d', CandleType.SPOT_) for p in pairlist
if p not in self._symbolsChecked and p not in self._symbolsCheckFailed]
if not needed_pairs:
# Remove pairs that have been removed before
@ -88,7 +89,8 @@ class AgeFilter(IPairList):
candles = self._exchange.refresh_latest_ohlcv(needed_pairs, since_ms=since_ms, cache=False)
if self._enabled:
for p in deepcopy(pairlist):
daily_candles = candles[(p, '1d', '')] if (p, '1d', '') in candles else None
daily_candles = candles[(p, '1d', CandleType.SPOT_)] if (
p, '1d', CandleType.SPOT_) in candles else None
if not self._validate_pair_loc(p, daily_candles):
pairlist.remove(p)
self.log_once(f"Validated {len(pairlist)} pairs.", logger.info)

View File

@ -5,7 +5,7 @@ import logging
import random
from typing import Any, Dict, List
from freqtrade.enums.runmode import RunMode
from freqtrade.enums import RunMode
from freqtrade.plugins.pairlist.IPairList import IPairList

View File

@ -11,6 +11,7 @@ import numpy as np
from cachetools.ttl import TTLCache
from pandas import DataFrame
from freqtrade.enums import CandleType
from freqtrade.exceptions import OperationalException
from freqtrade.misc import plural
from freqtrade.plugins.pairlist.IPairList import IPairList
@ -67,7 +68,7 @@ class VolatilityFilter(IPairList):
:param tickers: Tickers (from exchange.get_tickers()). May be cached.
:return: new allowlist
"""
needed_pairs = [(p, '1d', '') for p in pairlist if p not in self._pair_cache]
needed_pairs = [(p, '1d', CandleType.SPOT_) for p in pairlist if p not in self._pair_cache]
since_ms = (arrow.utcnow()
.floor('day')
@ -81,7 +82,8 @@ class VolatilityFilter(IPairList):
if self._enabled:
for p in deepcopy(pairlist):
daily_candles = candles[(p, '1d', '')] if (p, '1d', '') in candles else None
daily_candles = candles[(p, '1d', CandleType.SPOT_)] if (
p, '1d', CandleType.SPOT_) in candles else None
if not self._validate_pair_loc(p, daily_candles):
pairlist.remove(p)
return pairlist

View File

@ -10,6 +10,7 @@ from typing import Any, Dict, List
import arrow
from cachetools.ttl import TTLCache
from freqtrade.enums import CandleType
from freqtrade.exceptions import OperationalException
from freqtrade.exchange import timeframe_to_minutes
from freqtrade.misc import format_ms_time
@ -160,7 +161,7 @@ class VolumePairList(IPairList):
f"{self._lookback_timeframe}, starting from {format_ms_time(since_ms)} "
f"till {format_ms_time(to_ms)}", logger.info)
needed_pairs = [
(p, self._lookback_timeframe, '') for p in
(p, self._lookback_timeframe, CandleType.SPOT_) for p in
[s['symbol'] for s in filtered_tickers]
if p not in self._pair_cache
]
@ -173,8 +174,8 @@ class VolumePairList(IPairList):
)
for i, p in enumerate(filtered_tickers):
pair_candles = candles[
(p['symbol'], self._lookback_timeframe, '')
] if (p['symbol'], self._lookback_timeframe, '') in candles else None
(p['symbol'], self._lookback_timeframe, CandleType.SPOT_)
] if (p['symbol'], self._lookback_timeframe, CandleType.SPOT_) in candles else None
# in case of candle data calculate typical price and quoteVolume for candle
if pair_candles is not None and not pair_candles.empty:
pair_candles['typical_price'] = (pair_candles['high'] + pair_candles['low']

View File

@ -9,6 +9,7 @@ import arrow
from cachetools.ttl import TTLCache
from pandas import DataFrame
from freqtrade.enums import CandleType
from freqtrade.exceptions import OperationalException
from freqtrade.misc import plural
from freqtrade.plugins.pairlist.IPairList import IPairList
@ -65,7 +66,7 @@ class RangeStabilityFilter(IPairList):
:param tickers: Tickers (from exchange.get_tickers()). May be cached.
:return: new allowlist
"""
needed_pairs = [(p, '1d', '') for p in pairlist if p not in self._pair_cache]
needed_pairs = [(p, '1d', CandleType.SPOT_) for p in pairlist if p not in self._pair_cache]
since_ms = (arrow.utcnow()
.floor('day')
@ -79,7 +80,8 @@ class RangeStabilityFilter(IPairList):
if self._enabled:
for p in deepcopy(pairlist):
daily_candles = candles[(p, '1d', '')] if (p, '1d', '') in candles else None
daily_candles = candles[(p, '1d', CandleType.SPOT_)] if (
p, '1d', CandleType.SPOT_) in candles else None
if not self._validate_pair_loc(p, daily_candles):
pairlist.remove(p)
return pairlist

View File

@ -8,6 +8,7 @@ from typing import Dict, List
from cachetools import TTLCache, cached
from freqtrade.constants import ListPairsWithTimeframes
from freqtrade.enums import CandleType
from freqtrade.exceptions import OperationalException
from freqtrade.plugins.pairlist.IPairList import IPairList
from freqtrade.plugins.pairlist.pairlist_helpers import expand_pairlist
@ -138,4 +139,4 @@ class PairListManager():
"""
Create list of pair tuples with (pair, timeframe)
"""
return [(pair, timeframe or self._config['timeframe'], '') for pair in pairs]
return [(pair, timeframe or self._config['timeframe'], CandleType.SPOT) for pair in pairs]

View File

@ -9,6 +9,7 @@ from fastapi.exceptions import HTTPException
from freqtrade import __version__
from freqtrade.constants import USERPATH_STRATEGIES
from freqtrade.data.history import get_datahandler
from freqtrade.enums import CandleType
from freqtrade.exceptions import OperationalException
from freqtrade.rpc import RPC
from freqtrade.rpc.api_server.api_schemas import (AvailablePairs, Balances, BlacklistPayload,
@ -250,7 +251,7 @@ def get_strategy(strategy: str, config=Depends(get_config)):
@router.get('/available_pairs', response_model=AvailablePairs, tags=['candle data'])
def list_available_pairs(timeframe: Optional[str] = None, stake_currency: Optional[str] = None,
candletype: Optional[str] = None, config=Depends(get_config)):
candletype: Optional[CandleType] = None, config=Depends(get_config)):
dh = get_datahandler(config['datadir'], config.get('dataformat_ohlcv', None))

View File

@ -2,6 +2,7 @@ from typing import Any, Callable, NamedTuple, Optional, Union
from pandas import DataFrame
from freqtrade.enums import CandleType
from freqtrade.exceptions import OperationalException
from freqtrade.strategy.strategy_helper import merge_informative_pair
@ -14,7 +15,7 @@ class InformativeData(NamedTuple):
timeframe: str
fmt: Union[str, Callable[[Any], str], None]
ffill: bool
candle_type: str = ''
candle_type: CandleType = CandleType.SPOT_
def informative(timeframe: str, asset: str = '',

View File

@ -13,8 +13,7 @@ from pandas import DataFrame
from freqtrade.constants import ListPairsWithTimeframes
from freqtrade.data.dataprovider import DataProvider
from freqtrade.enums import SellType, SignalDirection, SignalTagType, SignalType
from freqtrade.enums.candletype import CandleType
from freqtrade.enums import CandleType, SellType, SignalDirection, SignalTagType, SignalType
from freqtrade.exceptions import OperationalException, StrategyError
from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds
from freqtrade.exchange.exchange import timeframe_to_next_date
@ -424,7 +423,9 @@ class IStrategy(ABC, HyperStrategyMixin):
"""
informative_pairs = self.informative_pairs()
# Compatibility code for 2 tuple informative pairs
informative_pairs = [(p[0], p[1], p[2] if len(p) > 2 else '') for p in informative_pairs]
informative_pairs = [
(p[0], p[1], CandleType.from_string(p[2]) if len(p) > 2 else CandleType.SPOT_)
for p in informative_pairs]
for inf_data, _ in self._ft_informative:
if inf_data.asset:
pair_tf = (