Merge branch 'develop' into add-spice-rack
This commit is contained in:
@@ -53,8 +53,8 @@ ARGS_LIST_PAIRS = ["exchange", "print_list", "list_pairs_print_json", "print_one
|
||||
"print_csv", "base_currencies", "quote_currencies", "list_pairs_all",
|
||||
"trading_mode"]
|
||||
|
||||
ARGS_TEST_PAIRLIST = ["verbosity", "config", "quote_currencies", "print_one_column",
|
||||
"list_pairs_print_json", "exchange"]
|
||||
ARGS_TEST_PAIRLIST = ["user_data_dir", "verbosity", "config", "quote_currencies",
|
||||
"print_one_column", "list_pairs_print_json", "exchange"]
|
||||
|
||||
ARGS_CREATE_USERDIR = ["user_data_dir", "reset"]
|
||||
|
||||
|
@@ -393,7 +393,8 @@ AVAILABLE_CLI_OPTIONS = {
|
||||
# Download data
|
||||
"pairs_file": Arg(
|
||||
'--pairs-file',
|
||||
help='File containing a list of pairs to download.',
|
||||
help='File containing a list of pairs. '
|
||||
'Takes precedence over --pairs or pairs configured in the configuration.',
|
||||
metavar='FILE',
|
||||
),
|
||||
"days": Arg(
|
||||
|
@@ -86,7 +86,7 @@ class DataProvider:
|
||||
"""
|
||||
_candle_type = CandleType.from_string(
|
||||
candle_type) if candle_type != '' else self._config['candle_type_def']
|
||||
saved_pair = (pair, str(timeframe), _candle_type)
|
||||
saved_pair: PairWithTimeframe = (pair, str(timeframe), _candle_type)
|
||||
if saved_pair not in self.__cached_pairs_backtesting:
|
||||
timerange = TimeRange.parse_timerange(None if self._config.get(
|
||||
'timerange') is None else str(self._config.get('timerange')))
|
||||
@@ -196,7 +196,9 @@ class DataProvider:
|
||||
Clear pair dataframe cache.
|
||||
"""
|
||||
self.__cached_pairs = {}
|
||||
self.__cached_pairs_backtesting = {}
|
||||
# Don't reset backtesting pairs -
|
||||
# otherwise they're reloaded each time during hyperopt due to with analyze_per_epoch
|
||||
# self.__cached_pairs_backtesting = {}
|
||||
self.__slice_index = 0
|
||||
|
||||
# Exchange functions
|
||||
|
@@ -31,7 +31,7 @@ class Binance(Exchange):
|
||||
"ccxt_futures_name": "future"
|
||||
}
|
||||
_ft_has_futures: Dict = {
|
||||
"stoploss_order_types": {"limit": "stop"},
|
||||
"stoploss_order_types": {"limit": "limit", "market": "market"},
|
||||
"tickers_have_price": False,
|
||||
}
|
||||
|
||||
@@ -48,13 +48,12 @@ class Binance(Exchange):
|
||||
Returns True if adjustment is necessary.
|
||||
:param side: "buy" or "sell"
|
||||
"""
|
||||
|
||||
ordertype = 'stop' if self.trading_mode == TradingMode.FUTURES else 'stop_loss_limit'
|
||||
order_types = ('stop_loss_limit', 'stop', 'stop_market')
|
||||
|
||||
return (
|
||||
order.get('stopPrice', None) is None
|
||||
or (
|
||||
order['type'] == ordertype
|
||||
order['type'] in order_types
|
||||
and (
|
||||
(side == "sell" and stop_loss > float(order['stopPrice'])) or
|
||||
(side == "buy" and stop_loss < float(order['stopPrice']))
|
||||
|
@@ -81,6 +81,104 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
"1000LUNC/USDT": [
|
||||
{
|
||||
"tier": 1.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 0.0,
|
||||
"maxNotional": 5000.0,
|
||||
"maintenanceMarginRate": 0.01,
|
||||
"maxLeverage": 25.0,
|
||||
"info": {
|
||||
"bracket": "1",
|
||||
"initialLeverage": "25",
|
||||
"notionalCap": "5000",
|
||||
"notionalFloor": "0",
|
||||
"maintMarginRatio": "0.01",
|
||||
"cum": "0.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 2.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 5000.0,
|
||||
"maxNotional": 25000.0,
|
||||
"maintenanceMarginRate": 0.025,
|
||||
"maxLeverage": 20.0,
|
||||
"info": {
|
||||
"bracket": "2",
|
||||
"initialLeverage": "20",
|
||||
"notionalCap": "25000",
|
||||
"notionalFloor": "5000",
|
||||
"maintMarginRatio": "0.025",
|
||||
"cum": "75.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 3.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 25000.0,
|
||||
"maxNotional": 100000.0,
|
||||
"maintenanceMarginRate": 0.05,
|
||||
"maxLeverage": 10.0,
|
||||
"info": {
|
||||
"bracket": "3",
|
||||
"initialLeverage": "10",
|
||||
"notionalCap": "100000",
|
||||
"notionalFloor": "25000",
|
||||
"maintMarginRatio": "0.05",
|
||||
"cum": "700.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 4.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 100000.0,
|
||||
"maxNotional": 250000.0,
|
||||
"maintenanceMarginRate": 0.1,
|
||||
"maxLeverage": 5.0,
|
||||
"info": {
|
||||
"bracket": "4",
|
||||
"initialLeverage": "5",
|
||||
"notionalCap": "250000",
|
||||
"notionalFloor": "100000",
|
||||
"maintMarginRatio": "0.1",
|
||||
"cum": "5700.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 5.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 250000.0,
|
||||
"maxNotional": 1000000.0,
|
||||
"maintenanceMarginRate": 0.125,
|
||||
"maxLeverage": 2.0,
|
||||
"info": {
|
||||
"bracket": "5",
|
||||
"initialLeverage": "2",
|
||||
"notionalCap": "1000000",
|
||||
"notionalFloor": "250000",
|
||||
"maintMarginRatio": "0.125",
|
||||
"cum": "11950.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 6.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 1000000.0,
|
||||
"maxNotional": 5000000.0,
|
||||
"maintenanceMarginRate": 0.5,
|
||||
"maxLeverage": 1.0,
|
||||
"info": {
|
||||
"bracket": "6",
|
||||
"initialLeverage": "1",
|
||||
"notionalCap": "5000000",
|
||||
"notionalFloor": "1000000",
|
||||
"maintMarginRatio": "0.5",
|
||||
"cum": "386950.0"
|
||||
}
|
||||
}
|
||||
],
|
||||
"1000SHIB/BUSD": [
|
||||
{
|
||||
"tier": 1.0,
|
||||
@@ -1109,6 +1207,88 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
"AMB/BUSD": [
|
||||
{
|
||||
"tier": 1.0,
|
||||
"currency": "BUSD",
|
||||
"minNotional": 0.0,
|
||||
"maxNotional": 25000.0,
|
||||
"maintenanceMarginRate": 0.025,
|
||||
"maxLeverage": 20.0,
|
||||
"info": {
|
||||
"bracket": "1",
|
||||
"initialLeverage": "20",
|
||||
"notionalCap": "25000",
|
||||
"notionalFloor": "0",
|
||||
"maintMarginRatio": "0.025",
|
||||
"cum": "0.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 2.0,
|
||||
"currency": "BUSD",
|
||||
"minNotional": 25000.0,
|
||||
"maxNotional": 100000.0,
|
||||
"maintenanceMarginRate": 0.05,
|
||||
"maxLeverage": 10.0,
|
||||
"info": {
|
||||
"bracket": "2",
|
||||
"initialLeverage": "10",
|
||||
"notionalCap": "100000",
|
||||
"notionalFloor": "25000",
|
||||
"maintMarginRatio": "0.05",
|
||||
"cum": "625.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 3.0,
|
||||
"currency": "BUSD",
|
||||
"minNotional": 100000.0,
|
||||
"maxNotional": 250000.0,
|
||||
"maintenanceMarginRate": 0.1,
|
||||
"maxLeverage": 5.0,
|
||||
"info": {
|
||||
"bracket": "3",
|
||||
"initialLeverage": "5",
|
||||
"notionalCap": "250000",
|
||||
"notionalFloor": "100000",
|
||||
"maintMarginRatio": "0.1",
|
||||
"cum": "5625.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 4.0,
|
||||
"currency": "BUSD",
|
||||
"minNotional": 250000.0,
|
||||
"maxNotional": 1000000.0,
|
||||
"maintenanceMarginRate": 0.125,
|
||||
"maxLeverage": 2.0,
|
||||
"info": {
|
||||
"bracket": "4",
|
||||
"initialLeverage": "2",
|
||||
"notionalCap": "1000000",
|
||||
"notionalFloor": "250000",
|
||||
"maintMarginRatio": "0.125",
|
||||
"cum": "11875.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 5.0,
|
||||
"currency": "BUSD",
|
||||
"minNotional": 1000000.0,
|
||||
"maxNotional": 5000000.0,
|
||||
"maintenanceMarginRate": 0.5,
|
||||
"maxLeverage": 1.0,
|
||||
"info": {
|
||||
"bracket": "5",
|
||||
"initialLeverage": "1",
|
||||
"notionalCap": "5000000",
|
||||
"notionalFloor": "1000000",
|
||||
"maintMarginRatio": "0.5",
|
||||
"cum": "386875.0"
|
||||
}
|
||||
}
|
||||
],
|
||||
"ANC/BUSD": [
|
||||
{
|
||||
"tier": 1.0,
|
||||
@@ -3300,13 +3480,13 @@
|
||||
"tier": 6.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 1000000.0,
|
||||
"maxNotional": 30000000.0,
|
||||
"maxNotional": 5000000.0,
|
||||
"maintenanceMarginRate": 0.5,
|
||||
"maxLeverage": 1.0,
|
||||
"info": {
|
||||
"bracket": "6",
|
||||
"initialLeverage": "1",
|
||||
"notionalCap": "30000000",
|
||||
"notionalCap": "5000000",
|
||||
"notionalFloor": "1000000",
|
||||
"maintMarginRatio": "0.5",
|
||||
"cum": "386950.0"
|
||||
@@ -4880,13 +5060,13 @@
|
||||
"tier": 6.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 1000000.0,
|
||||
"maxNotional": 30000000.0,
|
||||
"maxNotional": 5000000.0,
|
||||
"maintenanceMarginRate": 0.5,
|
||||
"maxLeverage": 1.0,
|
||||
"info": {
|
||||
"bracket": "6",
|
||||
"initialLeverage": "1",
|
||||
"notionalCap": "30000000",
|
||||
"notionalCap": "5000000",
|
||||
"notionalFloor": "1000000",
|
||||
"maintMarginRatio": "0.5",
|
||||
"cum": "386940.0"
|
||||
@@ -8333,6 +8513,104 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
"FOOTBALL/USDT": [
|
||||
{
|
||||
"tier": 1.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 0.0,
|
||||
"maxNotional": 5000.0,
|
||||
"maintenanceMarginRate": 0.01,
|
||||
"maxLeverage": 25.0,
|
||||
"info": {
|
||||
"bracket": "1",
|
||||
"initialLeverage": "25",
|
||||
"notionalCap": "5000",
|
||||
"notionalFloor": "0",
|
||||
"maintMarginRatio": "0.01",
|
||||
"cum": "0.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 2.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 5000.0,
|
||||
"maxNotional": 25000.0,
|
||||
"maintenanceMarginRate": 0.025,
|
||||
"maxLeverage": 20.0,
|
||||
"info": {
|
||||
"bracket": "2",
|
||||
"initialLeverage": "20",
|
||||
"notionalCap": "25000",
|
||||
"notionalFloor": "5000",
|
||||
"maintMarginRatio": "0.025",
|
||||
"cum": "75.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 3.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 25000.0,
|
||||
"maxNotional": 100000.0,
|
||||
"maintenanceMarginRate": 0.05,
|
||||
"maxLeverage": 10.0,
|
||||
"info": {
|
||||
"bracket": "3",
|
||||
"initialLeverage": "10",
|
||||
"notionalCap": "100000",
|
||||
"notionalFloor": "25000",
|
||||
"maintMarginRatio": "0.05",
|
||||
"cum": "700.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 4.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 100000.0,
|
||||
"maxNotional": 250000.0,
|
||||
"maintenanceMarginRate": 0.1,
|
||||
"maxLeverage": 5.0,
|
||||
"info": {
|
||||
"bracket": "4",
|
||||
"initialLeverage": "5",
|
||||
"notionalCap": "250000",
|
||||
"notionalFloor": "100000",
|
||||
"maintMarginRatio": "0.1",
|
||||
"cum": "5700.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 5.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 250000.0,
|
||||
"maxNotional": 1000000.0,
|
||||
"maintenanceMarginRate": 0.125,
|
||||
"maxLeverage": 2.0,
|
||||
"info": {
|
||||
"bracket": "5",
|
||||
"initialLeverage": "2",
|
||||
"notionalCap": "1000000",
|
||||
"notionalFloor": "250000",
|
||||
"maintMarginRatio": "0.125",
|
||||
"cum": "11950.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 6.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 1000000.0,
|
||||
"maxNotional": 5000000.0,
|
||||
"maintenanceMarginRate": 0.5,
|
||||
"maxLeverage": 1.0,
|
||||
"info": {
|
||||
"bracket": "6",
|
||||
"initialLeverage": "1",
|
||||
"notionalCap": "5000000",
|
||||
"notionalFloor": "1000000",
|
||||
"maintMarginRatio": "0.5",
|
||||
"cum": "386950.0"
|
||||
}
|
||||
}
|
||||
],
|
||||
"FTM/BUSD": [
|
||||
{
|
||||
"tier": 1.0,
|
||||
@@ -12123,6 +12401,104 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
"LUNA2/USDT": [
|
||||
{
|
||||
"tier": 1.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 0.0,
|
||||
"maxNotional": 5000.0,
|
||||
"maintenanceMarginRate": 0.015,
|
||||
"maxLeverage": 25.0,
|
||||
"info": {
|
||||
"bracket": "1",
|
||||
"initialLeverage": "25",
|
||||
"notionalCap": "5000",
|
||||
"notionalFloor": "0",
|
||||
"maintMarginRatio": "0.015",
|
||||
"cum": "0.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 2.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 5000.0,
|
||||
"maxNotional": 25000.0,
|
||||
"maintenanceMarginRate": 0.025,
|
||||
"maxLeverage": 20.0,
|
||||
"info": {
|
||||
"bracket": "2",
|
||||
"initialLeverage": "20",
|
||||
"notionalCap": "25000",
|
||||
"notionalFloor": "5000",
|
||||
"maintMarginRatio": "0.025",
|
||||
"cum": "50.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 3.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 25000.0,
|
||||
"maxNotional": 100000.0,
|
||||
"maintenanceMarginRate": 0.05,
|
||||
"maxLeverage": 10.0,
|
||||
"info": {
|
||||
"bracket": "3",
|
||||
"initialLeverage": "10",
|
||||
"notionalCap": "100000",
|
||||
"notionalFloor": "25000",
|
||||
"maintMarginRatio": "0.05",
|
||||
"cum": "675.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 4.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 100000.0,
|
||||
"maxNotional": 250000.0,
|
||||
"maintenanceMarginRate": 0.1,
|
||||
"maxLeverage": 5.0,
|
||||
"info": {
|
||||
"bracket": "4",
|
||||
"initialLeverage": "5",
|
||||
"notionalCap": "250000",
|
||||
"notionalFloor": "100000",
|
||||
"maintMarginRatio": "0.1",
|
||||
"cum": "5675.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 5.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 250000.0,
|
||||
"maxNotional": 1000000.0,
|
||||
"maintenanceMarginRate": 0.125,
|
||||
"maxLeverage": 2.0,
|
||||
"info": {
|
||||
"bracket": "5",
|
||||
"initialLeverage": "2",
|
||||
"notionalCap": "1000000",
|
||||
"notionalFloor": "250000",
|
||||
"maintMarginRatio": "0.125",
|
||||
"cum": "11925.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 6.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 1000000.0,
|
||||
"maxNotional": 5000000.0,
|
||||
"maintenanceMarginRate": 0.5,
|
||||
"maxLeverage": 1.0,
|
||||
"info": {
|
||||
"bracket": "6",
|
||||
"initialLeverage": "1",
|
||||
"notionalCap": "5000000",
|
||||
"notionalFloor": "1000000",
|
||||
"maintMarginRatio": "0.5",
|
||||
"cum": "386925.0"
|
||||
}
|
||||
}
|
||||
],
|
||||
"MANA/USDT": [
|
||||
{
|
||||
"tier": 1.0,
|
||||
@@ -13028,10 +13404,10 @@
|
||||
"minNotional": 0.0,
|
||||
"maxNotional": 5000.0,
|
||||
"maintenanceMarginRate": 0.01,
|
||||
"maxLeverage": 50.0,
|
||||
"maxLeverage": 25.0,
|
||||
"info": {
|
||||
"bracket": "1",
|
||||
"initialLeverage": "50",
|
||||
"initialLeverage": "25",
|
||||
"notionalCap": "5000",
|
||||
"notionalFloor": "0",
|
||||
"maintMarginRatio": "0.01",
|
||||
@@ -13805,6 +14181,88 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
"PHB/BUSD": [
|
||||
{
|
||||
"tier": 1.0,
|
||||
"currency": "BUSD",
|
||||
"minNotional": 0.0,
|
||||
"maxNotional": 25000.0,
|
||||
"maintenanceMarginRate": 0.025,
|
||||
"maxLeverage": 20.0,
|
||||
"info": {
|
||||
"bracket": "1",
|
||||
"initialLeverage": "20",
|
||||
"notionalCap": "25000",
|
||||
"notionalFloor": "0",
|
||||
"maintMarginRatio": "0.025",
|
||||
"cum": "0.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 2.0,
|
||||
"currency": "BUSD",
|
||||
"minNotional": 25000.0,
|
||||
"maxNotional": 100000.0,
|
||||
"maintenanceMarginRate": 0.05,
|
||||
"maxLeverage": 10.0,
|
||||
"info": {
|
||||
"bracket": "2",
|
||||
"initialLeverage": "10",
|
||||
"notionalCap": "100000",
|
||||
"notionalFloor": "25000",
|
||||
"maintMarginRatio": "0.05",
|
||||
"cum": "625.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 3.0,
|
||||
"currency": "BUSD",
|
||||
"minNotional": 100000.0,
|
||||
"maxNotional": 250000.0,
|
||||
"maintenanceMarginRate": 0.1,
|
||||
"maxLeverage": 5.0,
|
||||
"info": {
|
||||
"bracket": "3",
|
||||
"initialLeverage": "5",
|
||||
"notionalCap": "250000",
|
||||
"notionalFloor": "100000",
|
||||
"maintMarginRatio": "0.1",
|
||||
"cum": "5625.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 4.0,
|
||||
"currency": "BUSD",
|
||||
"minNotional": 250000.0,
|
||||
"maxNotional": 1000000.0,
|
||||
"maintenanceMarginRate": 0.125,
|
||||
"maxLeverage": 2.0,
|
||||
"info": {
|
||||
"bracket": "4",
|
||||
"initialLeverage": "2",
|
||||
"notionalCap": "1000000",
|
||||
"notionalFloor": "250000",
|
||||
"maintMarginRatio": "0.125",
|
||||
"cum": "11875.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 5.0,
|
||||
"currency": "BUSD",
|
||||
"minNotional": 1000000.0,
|
||||
"maxNotional": 5000000.0,
|
||||
"maintenanceMarginRate": 0.5,
|
||||
"maxLeverage": 1.0,
|
||||
"info": {
|
||||
"bracket": "5",
|
||||
"initialLeverage": "1",
|
||||
"notionalCap": "5000000",
|
||||
"notionalFloor": "1000000",
|
||||
"maintMarginRatio": "0.5",
|
||||
"cum": "386875.0"
|
||||
}
|
||||
}
|
||||
],
|
||||
"QTUM/USDT": [
|
||||
{
|
||||
"tier": 1.0,
|
||||
@@ -14008,10 +14466,10 @@
|
||||
"minNotional": 0.0,
|
||||
"maxNotional": 5000.0,
|
||||
"maintenanceMarginRate": 0.01,
|
||||
"maxLeverage": 50.0,
|
||||
"maxLeverage": 25.0,
|
||||
"info": {
|
||||
"bracket": "1",
|
||||
"initialLeverage": "50",
|
||||
"initialLeverage": "25",
|
||||
"notionalCap": "5000",
|
||||
"notionalFloor": "0",
|
||||
"maintMarginRatio": "0.01",
|
||||
@@ -14478,13 +14936,13 @@
|
||||
"tier": 6.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 1000000.0,
|
||||
"maxNotional": 30000000.0,
|
||||
"maxNotional": 5000000.0,
|
||||
"maintenanceMarginRate": 0.5,
|
||||
"maxLeverage": 1.0,
|
||||
"info": {
|
||||
"bracket": "6",
|
||||
"initialLeverage": "1",
|
||||
"notionalCap": "30000000",
|
||||
"notionalCap": "5000000",
|
||||
"notionalFloor": "1000000",
|
||||
"maintMarginRatio": "0.5",
|
||||
"cum": "386950.0"
|
||||
@@ -14576,13 +15034,13 @@
|
||||
"tier": 6.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 1000000.0,
|
||||
"maxNotional": 30000000.0,
|
||||
"maxNotional": 5000000.0,
|
||||
"maintenanceMarginRate": 0.5,
|
||||
"maxLeverage": 1.0,
|
||||
"info": {
|
||||
"bracket": "6",
|
||||
"initialLeverage": "1",
|
||||
"notionalCap": "30000000",
|
||||
"notionalCap": "5000000",
|
||||
"notionalFloor": "1000000",
|
||||
"maintMarginRatio": "0.5",
|
||||
"cum": "386950.0"
|
||||
@@ -15487,6 +15945,104 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
"SPELL/USDT": [
|
||||
{
|
||||
"tier": 1.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 0.0,
|
||||
"maxNotional": 5000.0,
|
||||
"maintenanceMarginRate": 0.01,
|
||||
"maxLeverage": 25.0,
|
||||
"info": {
|
||||
"bracket": "1",
|
||||
"initialLeverage": "25",
|
||||
"notionalCap": "5000",
|
||||
"notionalFloor": "0",
|
||||
"maintMarginRatio": "0.01",
|
||||
"cum": "0.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 2.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 5000.0,
|
||||
"maxNotional": 25000.0,
|
||||
"maintenanceMarginRate": 0.025,
|
||||
"maxLeverage": 20.0,
|
||||
"info": {
|
||||
"bracket": "2",
|
||||
"initialLeverage": "20",
|
||||
"notionalCap": "25000",
|
||||
"notionalFloor": "5000",
|
||||
"maintMarginRatio": "0.025",
|
||||
"cum": "75.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 3.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 25000.0,
|
||||
"maxNotional": 100000.0,
|
||||
"maintenanceMarginRate": 0.05,
|
||||
"maxLeverage": 10.0,
|
||||
"info": {
|
||||
"bracket": "3",
|
||||
"initialLeverage": "10",
|
||||
"notionalCap": "100000",
|
||||
"notionalFloor": "25000",
|
||||
"maintMarginRatio": "0.05",
|
||||
"cum": "700.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 4.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 100000.0,
|
||||
"maxNotional": 250000.0,
|
||||
"maintenanceMarginRate": 0.1,
|
||||
"maxLeverage": 5.0,
|
||||
"info": {
|
||||
"bracket": "4",
|
||||
"initialLeverage": "5",
|
||||
"notionalCap": "250000",
|
||||
"notionalFloor": "100000",
|
||||
"maintMarginRatio": "0.1",
|
||||
"cum": "5700.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 5.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 250000.0,
|
||||
"maxNotional": 1000000.0,
|
||||
"maintenanceMarginRate": 0.125,
|
||||
"maxLeverage": 2.0,
|
||||
"info": {
|
||||
"bracket": "5",
|
||||
"initialLeverage": "2",
|
||||
"notionalCap": "1000000",
|
||||
"notionalFloor": "250000",
|
||||
"maintMarginRatio": "0.125",
|
||||
"cum": "11950.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 6.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 1000000.0,
|
||||
"maxNotional": 5000000.0,
|
||||
"maintenanceMarginRate": 0.5,
|
||||
"maxLeverage": 1.0,
|
||||
"info": {
|
||||
"bracket": "6",
|
||||
"initialLeverage": "1",
|
||||
"notionalCap": "5000000",
|
||||
"notionalFloor": "1000000",
|
||||
"maintMarginRatio": "0.5",
|
||||
"cum": "386950.0"
|
||||
}
|
||||
}
|
||||
],
|
||||
"SRM/USDT": [
|
||||
{
|
||||
"tier": 1.0,
|
||||
@@ -15585,6 +16141,104 @@
|
||||
}
|
||||
}
|
||||
],
|
||||
"STG/USDT": [
|
||||
{
|
||||
"tier": 1.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 0.0,
|
||||
"maxNotional": 5000.0,
|
||||
"maintenanceMarginRate": 0.01,
|
||||
"maxLeverage": 25.0,
|
||||
"info": {
|
||||
"bracket": "1",
|
||||
"initialLeverage": "25",
|
||||
"notionalCap": "5000",
|
||||
"notionalFloor": "0",
|
||||
"maintMarginRatio": "0.01",
|
||||
"cum": "0.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 2.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 5000.0,
|
||||
"maxNotional": 25000.0,
|
||||
"maintenanceMarginRate": 0.025,
|
||||
"maxLeverage": 20.0,
|
||||
"info": {
|
||||
"bracket": "2",
|
||||
"initialLeverage": "20",
|
||||
"notionalCap": "25000",
|
||||
"notionalFloor": "5000",
|
||||
"maintMarginRatio": "0.025",
|
||||
"cum": "75.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 3.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 25000.0,
|
||||
"maxNotional": 100000.0,
|
||||
"maintenanceMarginRate": 0.05,
|
||||
"maxLeverage": 10.0,
|
||||
"info": {
|
||||
"bracket": "3",
|
||||
"initialLeverage": "10",
|
||||
"notionalCap": "100000",
|
||||
"notionalFloor": "25000",
|
||||
"maintMarginRatio": "0.05",
|
||||
"cum": "700.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 4.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 100000.0,
|
||||
"maxNotional": 250000.0,
|
||||
"maintenanceMarginRate": 0.1,
|
||||
"maxLeverage": 5.0,
|
||||
"info": {
|
||||
"bracket": "4",
|
||||
"initialLeverage": "5",
|
||||
"notionalCap": "250000",
|
||||
"notionalFloor": "100000",
|
||||
"maintMarginRatio": "0.1",
|
||||
"cum": "5700.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 5.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 250000.0,
|
||||
"maxNotional": 1000000.0,
|
||||
"maintenanceMarginRate": 0.125,
|
||||
"maxLeverage": 2.0,
|
||||
"info": {
|
||||
"bracket": "5",
|
||||
"initialLeverage": "2",
|
||||
"notionalCap": "1000000",
|
||||
"notionalFloor": "250000",
|
||||
"maintMarginRatio": "0.125",
|
||||
"cum": "11950.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tier": 6.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 1000000.0,
|
||||
"maxNotional": 5000000.0,
|
||||
"maintenanceMarginRate": 0.5,
|
||||
"maxLeverage": 1.0,
|
||||
"info": {
|
||||
"bracket": "6",
|
||||
"initialLeverage": "1",
|
||||
"notionalCap": "5000000",
|
||||
"notionalFloor": "1000000",
|
||||
"maintMarginRatio": "0.5",
|
||||
"cum": "386950.0"
|
||||
}
|
||||
}
|
||||
],
|
||||
"STMX/USDT": [
|
||||
{
|
||||
"tier": 1.0,
|
||||
@@ -16176,13 +16830,13 @@
|
||||
"tier": 5.0,
|
||||
"currency": "BUSD",
|
||||
"minNotional": 1000000.0,
|
||||
"maxNotional": 30000000.0,
|
||||
"maxNotional": 5000000.0,
|
||||
"maintenanceMarginRate": 0.5,
|
||||
"maxLeverage": 1.0,
|
||||
"info": {
|
||||
"bracket": "5",
|
||||
"initialLeverage": "1",
|
||||
"notionalCap": "30000000",
|
||||
"notionalCap": "5000000",
|
||||
"notionalFloor": "1000000",
|
||||
"maintMarginRatio": "0.5",
|
||||
"cum": "386875.0"
|
||||
@@ -16470,13 +17124,13 @@
|
||||
"tier": 6.0,
|
||||
"currency": "USDT",
|
||||
"minNotional": 1000000.0,
|
||||
"maxNotional": 30000000.0,
|
||||
"maxNotional": 5000000.0,
|
||||
"maintenanceMarginRate": 0.5,
|
||||
"maxLeverage": 1.0,
|
||||
"info": {
|
||||
"bracket": "6",
|
||||
"initialLeverage": "1",
|
||||
"notionalCap": "30000000",
|
||||
"notionalCap": "5000000",
|
||||
"notionalFloor": "1000000",
|
||||
"maintMarginRatio": "0.5",
|
||||
"cum": "386950.0"
|
||||
|
@@ -2304,7 +2304,7 @@ class Exchange:
|
||||
updated = tiers.get('updated')
|
||||
if updated:
|
||||
updated_dt = parser.parse(updated)
|
||||
if updated_dt < datetime.now(timezone.utc) - timedelta(days=1):
|
||||
if updated_dt < datetime.now(timezone.utc) - timedelta(weeks=4):
|
||||
logger.info("Cached leverage tiers are outdated. Will update.")
|
||||
return None
|
||||
return tiers['data']
|
||||
|
@@ -355,7 +355,7 @@ class FreqaiDataDrawer:
|
||||
for dir in model_folders:
|
||||
result = pattern.match(str(dir.name))
|
||||
if result is None:
|
||||
break
|
||||
continue
|
||||
coin = result.group(1)
|
||||
timestamp = result.group(2)
|
||||
|
||||
|
85
freqtrade/freqai/prediction_models/XGBoostClassifier.py
Normal file
85
freqtrade/freqai/prediction_models/XGBoostClassifier.py
Normal file
@@ -0,0 +1,85 @@
|
||||
import logging
|
||||
from typing import Any, Dict, Tuple
|
||||
|
||||
import numpy as np
|
||||
import numpy.typing as npt
|
||||
import pandas as pd
|
||||
from pandas import DataFrame
|
||||
from pandas.api.types import is_integer_dtype
|
||||
from sklearn.preprocessing import LabelEncoder
|
||||
from xgboost import XGBClassifier
|
||||
|
||||
from freqtrade.freqai.base_models.BaseClassifierModel import BaseClassifierModel
|
||||
from freqtrade.freqai.data_kitchen import FreqaiDataKitchen
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class XGBoostClassifier(BaseClassifierModel):
|
||||
"""
|
||||
User created prediction model. The class needs to override three necessary
|
||||
functions, predict(), train(), fit(). The class inherits ModelHandler which
|
||||
has its own DataHandler where data is held, saved, loaded, and managed.
|
||||
"""
|
||||
|
||||
def fit(self, data_dictionary: Dict, dk: FreqaiDataKitchen, **kwargs) -> Any:
|
||||
"""
|
||||
User sets up the training and test data to fit their desired model here
|
||||
:params:
|
||||
:data_dictionary: the dictionary constructed by DataHandler to hold
|
||||
all the training and test data/labels.
|
||||
"""
|
||||
|
||||
X = data_dictionary["train_features"].to_numpy()
|
||||
y = data_dictionary["train_labels"].to_numpy()[:, 0]
|
||||
|
||||
le = LabelEncoder()
|
||||
if not is_integer_dtype(y):
|
||||
y = pd.Series(le.fit_transform(y), dtype="int64")
|
||||
|
||||
if self.freqai_info.get('data_split_parameters', {}).get('test_size', 0.1) == 0:
|
||||
eval_set = None
|
||||
else:
|
||||
test_features = data_dictionary["test_features"].to_numpy()
|
||||
test_labels = data_dictionary["test_labels"].to_numpy()[:, 0]
|
||||
|
||||
if not is_integer_dtype(test_labels):
|
||||
test_labels = pd.Series(le.transform(test_labels), dtype="int64")
|
||||
|
||||
eval_set = [(test_features, test_labels)]
|
||||
|
||||
train_weights = data_dictionary["train_weights"]
|
||||
|
||||
init_model = self.get_init_model(dk.pair)
|
||||
|
||||
model = XGBClassifier(**self.model_training_parameters)
|
||||
|
||||
model.fit(X=X, y=y, eval_set=eval_set, sample_weight=train_weights,
|
||||
xgb_model=init_model)
|
||||
|
||||
return model
|
||||
|
||||
def predict(
|
||||
self, unfiltered_df: DataFrame, dk: FreqaiDataKitchen, **kwargs
|
||||
) -> Tuple[DataFrame, npt.NDArray[np.int_]]:
|
||||
"""
|
||||
Filter the prediction features data and predict with it.
|
||||
:param: unfiltered_df: Full dataframe for the current backtest period.
|
||||
:return:
|
||||
:pred_df: dataframe containing the predictions
|
||||
:do_predict: np.array of 1s and 0s to indicate places where freqai needed to remove
|
||||
data (NaNs) or felt uncertain about data (PCA and DI index)
|
||||
"""
|
||||
|
||||
(pred_df, dk.do_predict) = super().predict(unfiltered_df, dk, **kwargs)
|
||||
|
||||
le = LabelEncoder()
|
||||
label = dk.label_list[0]
|
||||
labels_before = list(dk.data['labels_std'].keys())
|
||||
labels_after = le.fit_transform(labels_before).tolist()
|
||||
pred_df[label] = le.inverse_transform(pred_df[label])
|
||||
pred_df = pred_df.rename(
|
||||
columns={labels_after[i]: labels_before[i] for i in range(len(labels_before))})
|
||||
|
||||
return (pred_df, dk.do_predict)
|
@@ -1072,6 +1072,7 @@ class FreqtradeBot(LoggingMixin):
|
||||
order_obj = Order.parse_from_ccxt_object(stoploss_order, trade.pair, 'stoploss')
|
||||
trade.orders.append(order_obj)
|
||||
trade.stoploss_order_id = str(stoploss_order['id'])
|
||||
trade.stoploss_last_update = datetime.now(timezone.utc)
|
||||
return True
|
||||
except InsufficientFundsError as e:
|
||||
logger.warning(f"Unable to place stoploss order {e}.")
|
||||
@@ -1145,10 +1146,9 @@ class FreqtradeBot(LoggingMixin):
|
||||
if self.create_stoploss_order(trade=trade, stop_price=stop_price):
|
||||
# The above will return False if the placement failed and the trade was force-sold.
|
||||
# in which case the trade will be closed - which we must check below.
|
||||
trade.stoploss_last_update = datetime.utcnow()
|
||||
return False
|
||||
|
||||
# If stoploss order is canceled for some reason we add it
|
||||
# If stoploss order is canceled for some reason we add it again
|
||||
if (trade.is_open
|
||||
and stoploss_order
|
||||
and stoploss_order['status'] in ('canceled', 'cancelled')):
|
||||
@@ -1186,7 +1186,8 @@ class FreqtradeBot(LoggingMixin):
|
||||
if self.exchange.stoploss_adjust(stoploss_norm, order, side=trade.exit_side):
|
||||
# we check if the update is necessary
|
||||
update_beat = self.strategy.order_types.get('stoploss_on_exchange_interval', 60)
|
||||
if (datetime.utcnow() - trade.stoploss_last_update).total_seconds() >= update_beat:
|
||||
upd_req = datetime.now(timezone.utc) - timedelta(seconds=update_beat)
|
||||
if trade.stoploss_last_update_utc and upd_req >= trade.stoploss_last_update_utc:
|
||||
# cancelling the current stoploss on exchange first
|
||||
logger.info(f"Cancelling current stoploss on exchange for pair {trade.pair} "
|
||||
f"(orderid:{order['id']}) in order to add another one ...")
|
||||
|
@@ -812,14 +812,6 @@ class Backtesting:
|
||||
return trade
|
||||
time_in_force = self.strategy.order_time_in_force['entry']
|
||||
|
||||
if not pos_adjust:
|
||||
# Confirm trade entry:
|
||||
if not strategy_safe_wrapper(self.strategy.confirm_trade_entry, default_retval=True)(
|
||||
pair=pair, order_type=order_type, amount=stake_amount, rate=propose_rate,
|
||||
time_in_force=time_in_force, current_time=current_time,
|
||||
entry_tag=entry_tag, side=direction):
|
||||
return trade
|
||||
|
||||
if stake_amount and (not min_stake_amount or stake_amount > min_stake_amount):
|
||||
self.order_id_counter += 1
|
||||
base_currency = self.exchange.get_pair_base_currency(pair)
|
||||
@@ -834,6 +826,15 @@ class Backtesting:
|
||||
# Backcalculate actual stake amount.
|
||||
stake_amount = amount * propose_rate / leverage
|
||||
|
||||
if not pos_adjust:
|
||||
# Confirm trade entry:
|
||||
if not strategy_safe_wrapper(
|
||||
self.strategy.confirm_trade_entry, default_retval=True)(
|
||||
pair=pair, order_type=order_type, amount=amount, rate=propose_rate,
|
||||
time_in_force=time_in_force, current_time=current_time,
|
||||
entry_tag=entry_tag, side=direction):
|
||||
return trade
|
||||
|
||||
is_short = (direction == 'short')
|
||||
# Necessary for Margin trading. Disabled until support is enabled.
|
||||
# interest_rate = self.exchange.get_interest_rate()
|
||||
|
@@ -290,7 +290,7 @@ class Hyperopt:
|
||||
# noinspection PyProtectedMember
|
||||
attr.value = params_dict[attr_name]
|
||||
|
||||
def generate_optimizer(self, raw_params: List[Any], iteration=None) -> Dict:
|
||||
def generate_optimizer(self, raw_params: List[Any]) -> Dict[str, Any]:
|
||||
"""
|
||||
Used Optimize function.
|
||||
Called once per epoch to optimize whatever is configured.
|
||||
@@ -410,9 +410,11 @@ class Hyperopt:
|
||||
model_queue_size=SKOPT_MODEL_QUEUE_SIZE,
|
||||
)
|
||||
|
||||
def run_optimizer_parallel(self, parallel, asked, i) -> List:
|
||||
def run_optimizer_parallel(
|
||||
self, parallel: Parallel, asked: List[List]) -> List[Dict[str, Any]]:
|
||||
""" Start optimizer in a parallel way """
|
||||
return parallel(delayed(
|
||||
wrap_non_picklable_objects(self.generate_optimizer))(v, i) for v in asked)
|
||||
wrap_non_picklable_objects(self.generate_optimizer))(v) for v in asked)
|
||||
|
||||
def _set_random_state(self, random_state: Optional[int]) -> int:
|
||||
return random_state or random.randint(1, 2**16 - 1)
|
||||
@@ -491,6 +493,53 @@ class Hyperopt:
|
||||
else:
|
||||
return self.opt.ask(n_points=n_points), [False for _ in range(n_points)]
|
||||
|
||||
def get_progressbar_widgets(self):
|
||||
if self.print_colorized:
|
||||
widgets = [
|
||||
' [Epoch ', progressbar.Counter(), ' of ', str(self.total_epochs),
|
||||
' (', progressbar.Percentage(), ')] ',
|
||||
progressbar.Bar(marker=progressbar.AnimatedMarker(
|
||||
fill='\N{FULL BLOCK}',
|
||||
fill_wrap=Fore.GREEN + '{}' + Fore.RESET,
|
||||
marker_wrap=Style.BRIGHT + '{}' + Style.RESET_ALL,
|
||||
)),
|
||||
' [', progressbar.ETA(), ', ', progressbar.Timer(), ']',
|
||||
]
|
||||
else:
|
||||
widgets = [
|
||||
' [Epoch ', progressbar.Counter(), ' of ', str(self.total_epochs),
|
||||
' (', progressbar.Percentage(), ')] ',
|
||||
progressbar.Bar(marker=progressbar.AnimatedMarker(
|
||||
fill='\N{FULL BLOCK}',
|
||||
)),
|
||||
' [', progressbar.ETA(), ', ', progressbar.Timer(), ']',
|
||||
]
|
||||
return widgets
|
||||
|
||||
def evaluate_result(self, val: Dict[str, Any], current: int, is_random: bool):
|
||||
"""
|
||||
Evaluate results returned from generate_optimizer
|
||||
"""
|
||||
val['current_epoch'] = current
|
||||
val['is_initial_point'] = current <= INITIAL_POINTS
|
||||
|
||||
logger.debug("Optimizer epoch evaluated: %s", val)
|
||||
|
||||
is_best = HyperoptTools.is_best_loss(val, self.current_best_loss)
|
||||
# This value is assigned here and not in the optimization method
|
||||
# to keep proper order in the list of results. That's because
|
||||
# evaluations can take different time. Here they are aligned in the
|
||||
# order they will be shown to the user.
|
||||
val['is_best'] = is_best
|
||||
val['is_random'] = is_random
|
||||
self.print_results(val)
|
||||
|
||||
if is_best:
|
||||
self.current_best_loss = val['loss']
|
||||
self.current_best_epoch = val
|
||||
|
||||
self._save_result(val)
|
||||
|
||||
def start(self) -> None:
|
||||
self.random_state = self._set_random_state(self.config.get('hyperopt_random_state'))
|
||||
logger.info(f"Using optimizer random state: {self.random_state}")
|
||||
@@ -526,64 +575,40 @@ class Hyperopt:
|
||||
logger.info(f'Effective number of parallel workers used: {jobs}')
|
||||
|
||||
# Define progressbar
|
||||
if self.print_colorized:
|
||||
widgets = [
|
||||
' [Epoch ', progressbar.Counter(), ' of ', str(self.total_epochs),
|
||||
' (', progressbar.Percentage(), ')] ',
|
||||
progressbar.Bar(marker=progressbar.AnimatedMarker(
|
||||
fill='\N{FULL BLOCK}',
|
||||
fill_wrap=Fore.GREEN + '{}' + Fore.RESET,
|
||||
marker_wrap=Style.BRIGHT + '{}' + Style.RESET_ALL,
|
||||
)),
|
||||
' [', progressbar.ETA(), ', ', progressbar.Timer(), ']',
|
||||
]
|
||||
else:
|
||||
widgets = [
|
||||
' [Epoch ', progressbar.Counter(), ' of ', str(self.total_epochs),
|
||||
' (', progressbar.Percentage(), ')] ',
|
||||
progressbar.Bar(marker=progressbar.AnimatedMarker(
|
||||
fill='\N{FULL BLOCK}',
|
||||
)),
|
||||
' [', progressbar.ETA(), ', ', progressbar.Timer(), ']',
|
||||
]
|
||||
widgets = self.get_progressbar_widgets()
|
||||
with progressbar.ProgressBar(
|
||||
max_value=self.total_epochs, redirect_stdout=False, redirect_stderr=False,
|
||||
widgets=widgets
|
||||
) as pbar:
|
||||
EVALS = ceil(self.total_epochs / jobs)
|
||||
for i in range(EVALS):
|
||||
start = 0
|
||||
|
||||
if self.analyze_per_epoch:
|
||||
# First analysis not in parallel mode when using --analyze-per-epoch.
|
||||
# This allows dataprovider to load it's informative cache.
|
||||
asked, is_random = self.get_asked_points(n_points=1)
|
||||
f_val0 = self.generate_optimizer(asked[0])
|
||||
self.opt.tell(asked, [f_val0['loss']])
|
||||
self.evaluate_result(f_val0, 1, is_random[0])
|
||||
pbar.update(1)
|
||||
start += 1
|
||||
|
||||
evals = ceil((self.total_epochs - start) / jobs)
|
||||
for i in range(evals):
|
||||
# Correct the number of epochs to be processed for the last
|
||||
# iteration (should not exceed self.total_epochs in total)
|
||||
n_rest = (i + 1) * jobs - self.total_epochs
|
||||
n_rest = (i + 1) * jobs - (self.total_epochs - start)
|
||||
current_jobs = jobs - n_rest if n_rest > 0 else jobs
|
||||
|
||||
asked, is_random = self.get_asked_points(n_points=current_jobs)
|
||||
f_val = self.run_optimizer_parallel(parallel, asked, i)
|
||||
f_val = self.run_optimizer_parallel(parallel, asked)
|
||||
self.opt.tell(asked, [v['loss'] for v in f_val])
|
||||
|
||||
# Calculate progressbar outputs
|
||||
for j, val in enumerate(f_val):
|
||||
# Use human-friendly indexes here (starting from 1)
|
||||
current = i * jobs + j + 1
|
||||
val['current_epoch'] = current
|
||||
val['is_initial_point'] = current <= INITIAL_POINTS
|
||||
current = i * jobs + j + 1 + start
|
||||
|
||||
logger.debug(f"Optimizer epoch evaluated: {val}")
|
||||
|
||||
is_best = HyperoptTools.is_best_loss(val, self.current_best_loss)
|
||||
# This value is assigned here and not in the optimization method
|
||||
# to keep proper order in the list of results. That's because
|
||||
# evaluations can take different time. Here they are aligned in the
|
||||
# order they will be shown to the user.
|
||||
val['is_best'] = is_best
|
||||
val['is_random'] = is_random[j]
|
||||
self.print_results(val)
|
||||
|
||||
if is_best:
|
||||
self.current_best_loss = val['loss']
|
||||
self.current_best_epoch = val
|
||||
|
||||
self._save_result(val)
|
||||
self.evaluate_result(val, current, is_random[j])
|
||||
|
||||
pbar.update(current)
|
||||
|
||||
|
@@ -83,7 +83,7 @@ class Order(_DECL_BASE):
|
||||
|
||||
@property
|
||||
def safe_price(self) -> float:
|
||||
return self.average or self.price
|
||||
return self.average or self.price or self.stop_price
|
||||
|
||||
@property
|
||||
def safe_filled(self) -> float:
|
||||
@@ -376,6 +376,12 @@ class LocalTrade():
|
||||
def open_date_utc(self):
|
||||
return self.open_date.replace(tzinfo=timezone.utc)
|
||||
|
||||
@property
|
||||
def stoploss_last_update_utc(self):
|
||||
if self.stoploss_last_update:
|
||||
return self.stoploss_last_update.replace(tzinfo=timezone.utc)
|
||||
return None
|
||||
|
||||
@property
|
||||
def close_date_utc(self):
|
||||
return self.close_date.replace(tzinfo=timezone.utc)
|
||||
@@ -560,7 +566,6 @@ class LocalTrade():
|
||||
self.stop_loss = stop_loss_norm
|
||||
|
||||
self.stop_loss_pct = -1 * abs(percent)
|
||||
self.stoploss_last_update = datetime.utcnow()
|
||||
|
||||
def adjust_stop_loss(self, current_price: float, stoploss: float,
|
||||
initial: bool = False, refresh: bool = False) -> None:
|
||||
|
@@ -684,6 +684,22 @@ class IStrategy(ABC, HyperStrategyMixin):
|
||||
# END - Intended to be overridden by strategy
|
||||
###
|
||||
|
||||
def __informative_pairs_freqai(self) -> ListPairsWithTimeframes:
|
||||
"""
|
||||
Create informative-pairs needed for FreqAI
|
||||
"""
|
||||
if self.config.get('freqai', {}).get('enabled', False):
|
||||
whitelist_pairs = self.dp.current_whitelist()
|
||||
candle_type = self.config.get('candle_type_def', CandleType.SPOT)
|
||||
corr_pairs = self.config["freqai"]["feature_parameters"]["include_corr_pairlist"]
|
||||
informative_pairs = []
|
||||
for tf in self.config["freqai"]["feature_parameters"]["include_timeframes"]:
|
||||
for pair in set(whitelist_pairs + corr_pairs):
|
||||
informative_pairs.append((pair, tf, candle_type))
|
||||
return informative_pairs
|
||||
|
||||
return []
|
||||
|
||||
def gather_informative_pairs(self) -> ListPairsWithTimeframes:
|
||||
"""
|
||||
Internal method which gathers all informative pairs (user or automatically defined).
|
||||
@@ -708,6 +724,7 @@ class IStrategy(ABC, HyperStrategyMixin):
|
||||
else:
|
||||
for pair in self.dp.current_whitelist():
|
||||
informative_pairs.append((pair, inf_data.timeframe, candle_type))
|
||||
informative_pairs.extend(self.__informative_pairs_freqai())
|
||||
return list(set(informative_pairs))
|
||||
|
||||
def get_strategy_name(self) -> str:
|
||||
|
@@ -47,19 +47,6 @@ class FreqaiExampleStrategy(IStrategy):
|
||||
std_dev_multiplier_sell = CategoricalParameter(
|
||||
[0.1, 0.25, 0.4], space="sell", default=0.2, optimize=True)
|
||||
|
||||
def informative_pairs(self):
|
||||
whitelist_pairs = self.dp.current_whitelist()
|
||||
corr_pairs = self.config["freqai"]["feature_parameters"]["include_corr_pairlist"]
|
||||
informative_pairs = []
|
||||
for tf in self.config["freqai"]["feature_parameters"]["include_timeframes"]:
|
||||
for pair in whitelist_pairs:
|
||||
informative_pairs.append((pair, tf))
|
||||
for pair in corr_pairs:
|
||||
if pair in whitelist_pairs:
|
||||
continue # avoid duplication
|
||||
informative_pairs.append((pair, tf))
|
||||
return informative_pairs
|
||||
|
||||
def populate_any_indicators(
|
||||
self, pair, df, tf, informative=None, set_generalized_indicators=False
|
||||
):
|
||||
|
@@ -95,20 +95,6 @@ class FreqaiExampleHybridStrategy(IStrategy):
|
||||
short_rsi = IntParameter(low=51, high=100, default=70, space='sell', optimize=True, load=True)
|
||||
exit_short_rsi = IntParameter(low=1, high=50, default=30, space='buy', optimize=True, load=True)
|
||||
|
||||
# FreqAI required function, leave as is or add additional informatives to existing structure.
|
||||
def informative_pairs(self):
|
||||
whitelist_pairs = self.dp.current_whitelist()
|
||||
corr_pairs = self.config["freqai"]["feature_parameters"]["include_corr_pairlist"]
|
||||
informative_pairs = []
|
||||
for tf in self.config["freqai"]["feature_parameters"]["include_timeframes"]:
|
||||
for pair in whitelist_pairs:
|
||||
informative_pairs.append((pair, tf))
|
||||
for pair in corr_pairs:
|
||||
if pair in whitelist_pairs:
|
||||
continue # avoid duplication
|
||||
informative_pairs.append((pair, tf))
|
||||
return informative_pairs
|
||||
|
||||
# FreqAI required function, user can add or remove indicators, but general structure
|
||||
# must stay the same.
|
||||
def populate_any_indicators(
|
||||
|
Reference in New Issue
Block a user