Revert "resolves freqtrade/freqtrade#4650"
This reverts commit 142690c930
.
This commit is contained in:
parent
142690c930
commit
6f02acdbbd
99
config_binance.json.example
Normal file
99
config_binance.json.example
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
{
|
||||||
|
"max_open_trades": 3,
|
||||||
|
"stake_currency": "BTC",
|
||||||
|
"stake_amount": 0.05,
|
||||||
|
"tradable_balance_ratio": 0.99,
|
||||||
|
"fiat_display_currency": "USD",
|
||||||
|
"timeframe": "5m",
|
||||||
|
"dry_run": true,
|
||||||
|
"cancel_open_orders_on_exit": false,
|
||||||
|
"unfilledtimeout": {
|
||||||
|
"buy": 10,
|
||||||
|
"sell": 30
|
||||||
|
},
|
||||||
|
"bid_strategy": {
|
||||||
|
"ask_last_balance": 0.0,
|
||||||
|
"use_order_book": false,
|
||||||
|
"order_book_top": 1,
|
||||||
|
"check_depth_of_market": {
|
||||||
|
"enabled": false,
|
||||||
|
"bids_to_ask_delta": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ask_strategy": {
|
||||||
|
"use_order_book": false,
|
||||||
|
"order_book_min": 1,
|
||||||
|
"order_book_max": 1,
|
||||||
|
"use_sell_signal": true,
|
||||||
|
"sell_profit_only": false,
|
||||||
|
"ignore_roi_if_buy_signal": false
|
||||||
|
},
|
||||||
|
"exchange": {
|
||||||
|
"name": "binance",
|
||||||
|
"key": "your_exchange_key",
|
||||||
|
"secret": "your_exchange_secret",
|
||||||
|
"ccxt_config": {"enableRateLimit": true},
|
||||||
|
"ccxt_async_config": {
|
||||||
|
"enableRateLimit": true,
|
||||||
|
"rateLimit": 200
|
||||||
|
},
|
||||||
|
"pair_whitelist": [
|
||||||
|
"ALGO/BTC",
|
||||||
|
"ATOM/BTC",
|
||||||
|
"BAT/BTC",
|
||||||
|
"BCH/BTC",
|
||||||
|
"BRD/BTC",
|
||||||
|
"EOS/BTC",
|
||||||
|
"ETH/BTC",
|
||||||
|
"IOTA/BTC",
|
||||||
|
"LINK/BTC",
|
||||||
|
"LTC/BTC",
|
||||||
|
"NEO/BTC",
|
||||||
|
"NXS/BTC",
|
||||||
|
"XMR/BTC",
|
||||||
|
"XRP/BTC",
|
||||||
|
"XTZ/BTC"
|
||||||
|
],
|
||||||
|
"pair_blacklist": [
|
||||||
|
"BNB/BTC"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"pairlists": [
|
||||||
|
{"method": "StaticPairList"}
|
||||||
|
],
|
||||||
|
"edge": {
|
||||||
|
"enabled": false,
|
||||||
|
"process_throttle_secs": 3600,
|
||||||
|
"calculate_since_number_of_days": 7,
|
||||||
|
"allowed_risk": 0.01,
|
||||||
|
"stoploss_range_min": -0.01,
|
||||||
|
"stoploss_range_max": -0.1,
|
||||||
|
"stoploss_range_step": -0.01,
|
||||||
|
"minimum_winrate": 0.60,
|
||||||
|
"minimum_expectancy": 0.20,
|
||||||
|
"min_trade_number": 10,
|
||||||
|
"max_trade_duration_minute": 1440,
|
||||||
|
"remove_pumps": false
|
||||||
|
},
|
||||||
|
"telegram": {
|
||||||
|
"enabled": false,
|
||||||
|
"token": "your_telegram_token",
|
||||||
|
"chat_id": "your_telegram_chat_id"
|
||||||
|
},
|
||||||
|
"api_server": {
|
||||||
|
"enabled": false,
|
||||||
|
"listen_ip_address": "127.0.0.1",
|
||||||
|
"listen_port": 8080,
|
||||||
|
"verbosity": "error",
|
||||||
|
"jwt_secret_key": "somethingrandom",
|
||||||
|
"CORS_origins": [],
|
||||||
|
"username": "freqtrader",
|
||||||
|
"password": "SuperSecurePassword"
|
||||||
|
},
|
||||||
|
"bot_name": "freqtrade",
|
||||||
|
"initial_state": "running",
|
||||||
|
"forcebuy_enable": false,
|
||||||
|
"internals": {
|
||||||
|
"process_throttle_secs": 5
|
||||||
|
}
|
||||||
|
}
|
@ -25,4 +25,4 @@ services:
|
|||||||
--logfile /freqtrade/user_data/logs/freqtrade.log
|
--logfile /freqtrade/user_data/logs/freqtrade.log
|
||||||
--db-url sqlite:////freqtrade/user_data/tradesv3.sqlite
|
--db-url sqlite:////freqtrade/user_data/tradesv3.sqlite
|
||||||
--config /freqtrade/user_data/config.json
|
--config /freqtrade/user_data/config.json
|
||||||
--strategy BinHV45.py
|
--strategy SampleStrategy
|
||||||
|
@ -26,7 +26,7 @@ HYPEROPT_LOSS_BUILTIN = ['ShortTradeDurHyperOptLoss', 'OnlyProfitHyperOptLoss',
|
|||||||
AVAILABLE_PAIRLISTS = ['StaticPairList', 'VolumePairList',
|
AVAILABLE_PAIRLISTS = ['StaticPairList', 'VolumePairList',
|
||||||
'AgeFilter', 'PerformanceFilter', 'PrecisionFilter',
|
'AgeFilter', 'PerformanceFilter', 'PrecisionFilter',
|
||||||
'PriceFilter', 'RangeStabilityFilter', 'ShuffleFilter',
|
'PriceFilter', 'RangeStabilityFilter', 'ShuffleFilter',
|
||||||
'SpreadFilter', 'VolatilityFilter']
|
'SpreadFilter']
|
||||||
AVAILABLE_PROTECTIONS = ['CooldownPeriod', 'LowProfitPairs', 'MaxDrawdown', 'StoplossGuard']
|
AVAILABLE_PROTECTIONS = ['CooldownPeriod', 'LowProfitPairs', 'MaxDrawdown', 'StoplossGuard']
|
||||||
AVAILABLE_DATAHANDLERS = ['json', 'jsongz', 'hdf5']
|
AVAILABLE_DATAHANDLERS = ['json', 'jsongz', 'hdf5']
|
||||||
DRY_RUN_WALLET = 1000
|
DRY_RUN_WALLET = 1000
|
||||||
@ -416,4 +416,4 @@ PairWithTimeframe = Tuple[str, str]
|
|||||||
ListPairsWithTimeframes = List[PairWithTimeframe]
|
ListPairsWithTimeframes = List[PairWithTimeframe]
|
||||||
|
|
||||||
# Type for trades list
|
# Type for trades list
|
||||||
TradeList = List[List]
|
TradeList = List[List]
|
||||||
|
@ -1,120 +0,0 @@
|
|||||||
"""
|
|
||||||
Rate of change pairlist filter
|
|
||||||
"""
|
|
||||||
import logging
|
|
||||||
from copy import deepcopy
|
|
||||||
from typing import Any, Dict, List, Optional
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import arrow
|
|
||||||
from cachetools.ttl import TTLCache
|
|
||||||
from pandas import DataFrame
|
|
||||||
import numpy as np
|
|
||||||
|
|
||||||
from freqtrade.exceptions import OperationalException
|
|
||||||
from freqtrade.misc import plural
|
|
||||||
from freqtrade.plugins.pairlist.IPairList import IPairList
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class VolatilityFilter(IPairList):
|
|
||||||
'''
|
|
||||||
Filters pairs by volatility
|
|
||||||
'''
|
|
||||||
|
|
||||||
def __init__(self, exchange, pairlistmanager,
|
|
||||||
config: Dict[str, Any], pairlistconfig: Dict[str, Any],
|
|
||||||
pairlist_pos: int) -> None:
|
|
||||||
super().__init__(exchange, pairlistmanager, config, pairlistconfig, pairlist_pos)
|
|
||||||
|
|
||||||
self._days = pairlistconfig.get('lookback_days', 10)
|
|
||||||
self._min_volatility = pairlistconfig.get('min_volatility', 0)
|
|
||||||
self._max_volatility = pairlistconfig.get('max_volatility', sys.maxsize)
|
|
||||||
self._refresh_period = pairlistconfig.get('refresh_period', 1440)
|
|
||||||
|
|
||||||
self._pair_cache: TTLCache = TTLCache(maxsize=1000, ttl=self._refresh_period)
|
|
||||||
|
|
||||||
if self._days < 1:
|
|
||||||
raise OperationalException("VolatilityFilter requires lookback_days to be >= 1")
|
|
||||||
if self._days > exchange.ohlcv_candle_limit('1d'):
|
|
||||||
raise OperationalException("VolatilityFilter requires lookback_days to not "
|
|
||||||
"exceed exchange max request size "
|
|
||||||
f"({exchange.ohlcv_candle_limit('1d')})")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def needstickers(self) -> bool:
|
|
||||||
"""
|
|
||||||
Boolean property defining if tickers are necessary.
|
|
||||||
If no Pairlist requires tickers, an empty List is passed
|
|
||||||
as tickers argument to filter_pairlist
|
|
||||||
"""
|
|
||||||
return False
|
|
||||||
|
|
||||||
def short_desc(self) -> str:
|
|
||||||
"""
|
|
||||||
Short whitelist method description - used for startup-messages
|
|
||||||
"""
|
|
||||||
return (f"{self.name} - Filtering pairs with volatility range "
|
|
||||||
f"{self._min_volatility}-{self._max_volatility} the last {self._days} {plural(self._days, 'day')}.")
|
|
||||||
|
|
||||||
def filter_pairlist(self, pairlist: List[str], tickers: Dict) -> List[str]:
|
|
||||||
"""
|
|
||||||
Validate trading range
|
|
||||||
:param pairlist: pairlist to filter or sort
|
|
||||||
:param tickers: Tickers (from exchange.get_tickers()). May be cached.
|
|
||||||
:return: new allowlist
|
|
||||||
"""
|
|
||||||
needed_pairs = [(p, '1h') for p in pairlist if p not in self._pair_cache]
|
|
||||||
|
|
||||||
since_ms = int(arrow.utcnow()
|
|
||||||
.floor('day')
|
|
||||||
.shift(days=-self._days - 1)
|
|
||||||
.float_timestamp) * 1000
|
|
||||||
# Get all candles
|
|
||||||
candles = {}
|
|
||||||
if needed_pairs:
|
|
||||||
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, '1h')] if (p, '1h') in candles else None
|
|
||||||
if not self._validate_pair_loc(p, daily_candles):
|
|
||||||
pairlist.remove(p)
|
|
||||||
return pairlist
|
|
||||||
|
|
||||||
def _validate_pair_loc(self, pair: str, daily_candles: Optional[DataFrame]) -> bool:
|
|
||||||
"""
|
|
||||||
Validate trading range
|
|
||||||
:param pair: Pair that's currently validated
|
|
||||||
:param ticker: ticker dict as returned from ccxt.load_markets()
|
|
||||||
:return: True if the pair can stay, false if it should be removed
|
|
||||||
"""
|
|
||||||
# Check symbol in cache
|
|
||||||
if pair in self._pair_cache:
|
|
||||||
return self._pair_cache[pair]
|
|
||||||
|
|
||||||
result = False
|
|
||||||
if daily_candles is not None and not daily_candles.empty:
|
|
||||||
returns = (np.log(daily_candles.close / daily_candles.close.shift(-1)))
|
|
||||||
returns.fillna(0, inplace=True)
|
|
||||||
|
|
||||||
volatility_series = returns.rolling(window=self._days*24).std()*np.sqrt(self._days*24)
|
|
||||||
volatility_avg = volatility_series.mean()
|
|
||||||
|
|
||||||
if self._min_volatility <= volatility_avg <= self._max_volatility:
|
|
||||||
result = True
|
|
||||||
else:
|
|
||||||
self.log_once(f"Removed {pair} from whitelist, because volatility "
|
|
||||||
f"over {self._days} {plural(self._days, 'day')} "
|
|
||||||
f"is: {volatility_avg:.3f} "
|
|
||||||
f"which is not in the configured range of "
|
|
||||||
f"{self._min_volatility}-{self._max_volatility}.",
|
|
||||||
logger.info)
|
|
||||||
result = False
|
|
||||||
self._pair_cache[pair] = result
|
|
||||||
|
|
||||||
return result
|
|
Loading…
Reference in New Issue
Block a user