Timeframe
15m
Direction
Long Only
Stoploss
-31.8%
Trailing Stop
No
ROI
0m: 21.5%, 40m: 13.2%, 87m: 8.6%, 360m: 3.0%
Interface Version
3
Startup Candles
89
Indicators
5
freqtrade/freqtrade-strategies
Strategy 003 author@: Gerald Lonlas github@: https://github.com/freqtrade/freqtrade-strategies
# freqtrade hyperopt --hyperopt-loss ProfitDrawDownHyperOptLoss --spaces roi trailing protection buy sell trades --strategy AWATRCT --config user_data/config_backtesting.json -e 200 -p `cat pairs34` --timerange 20240801- -j 3 --timeframe-detail 5m
#
# Hyperopt results
# ┏━━━━━━━━┳━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
# ┃ Best ┃ Epoch ┃ Trades ┃ Win Draw Loss Win% ┃ Avg profit ┃ Profit ┃ Avg duration ┃ Objective ┃ Max Drawdown (Acct) ┃
# ┡━━━━━━━━╇━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
# │ * Best │ 1/200 │ 124 │ 60 48 16 48.4 │ 0.31% │ 63.062 USDT (6.31%) │ 12:29:00 │ -57.58846 │ 96.888 USDT (9.38%) │
# │ * Best │ 4/200 │ 212 │ 86 115 11 40.6 │ 0.35% │ 110.718 USDT (11.07%) │ 6:02:00 │ -109.57862 │ 11.850 USDT (1.11%) │
# │ * Best │ 13/200 │ 112 │ 56 42 14 50.0 │ 0.49% │ 137.341 USDT (13.73%) │ 11:14:00 │ -128.90512 │ 68.666 USDT (6.64%) │
# │ Best │ 75/200 │ 90 │ 46 36 8 51.1 │ 0.49% │ 152.257 USDT (15.23%) │ 10:02:00 │ -140.19980 │ 90.589 USDT (8.56%) │
# │ Best │ 108/200 │ 42 │ 24 12 6 57.1 │ 0.50% │ 174.542 USDT (17.45%) │ 11:52:00 │ -161.57066 │ 84.972 USDT (8.03%) │
# │ Best** │ 157/200 │ 59 │ 33 20 6 55.9 │ 0.62% │ 184.604 USDT (18.46%) │ 9:48:00 │ -170.44132 │ 88.886 USDT (8.29%) │
# └────────┴─────────┴────────┴────────────────────────┴────────────┴─────────────────────────┴──────────────┴────────────┴────────────────────────┘
# --- Do not remove these libs ---
import math
from freqtrade.strategy.interface import IStrategy
from typing import Dict, List
from functools import reduce
from pandas import DataFrame
# --------------------------------
import talib.abstract as ta
import numpy as np
import freqtrade.vendor.qtpylib.indicators as qtpylib
import datetime
import pandas_ta as pta
import pandas as pd
from typing import Optional
from technical.util import resample_to_interval, resampled_merge
from datetime import datetime, timedelta
from freqtrade.persistence import Trade
from freqtrade.strategy import BooleanParameter, stoploss_from_open, merge_informative_pair, DecimalParameter, IntParameter, \
CategoricalParameter
import technical.indicators as ftt
from freqtrade.exchange import timeframe_to_minutes
# Buy hyperspace params:
buy_params = {
"base_nb_candles_buy": 20,
"ewof": 8,
"ewos": 89,
"ewo_high_mult": 1.3618,
"ewo_bear_mult": 1.65,
"ewo_bull_mult": 1.01618,
"low_offset": 0.95, # 34, # 0.942 for BTC and 0.934 for USDT
"rsi_buy": 61 # with regular ewo 45
}
# Sell hyperspace params:
sell_params = {
"base_nb_candles_sell": 45,
"high_offset": 1.01918 # 1.019
}
def EWO(dataframe, ema_length=8, ema2_length=89):
df = dataframe.copy()
ema1 = ta.EMA(df, timeperiod=ema_length.value)
ema2 = ta.EMA(df, timeperiod=ema2_length.value)
emadif = (ema1 - ema2) / df['close'] * 100
return emadif
def calculate_murrey_math_levels(df, window_size=64):
df = df.iloc[-window_size:]
# Calculate rolling 64-bar maximum and minimum values
rolling_max_H = df['high'].rolling(window=window_size).max()
rolling_min_L = df['low'].rolling(window=window_size).min()
max_H = rolling_max_H
min_L = rolling_min_L
range_HL = max_H - min_L
def calculate_fractal(v2):
fractal = 0
if 25000 < v2 <= 250000:
fractal = 100000
elif 2500 < v2 <= 25000:
fractal = 10000
elif 250 < v2 <= 2500:
fractal = 1000
elif 25 < v2 <= 250:
fractal = 100
elif 12.5 < v2 <= 25:
fractal = 12.5
elif 6.25 < v2 <= 12.5:
fractal = 12.5
elif 3.125 < v2 <= 6.25:
fractal = 6.25
elif 1.5625 < v2 <= 3.125:
fractal = 3.125
elif 0.390625 < v2 <= 1.5625:
fractal = 1.5625
elif 0 < v2 <= 0.390625:
fractal = 0.1953125
return fractal
def calculate_octave(v1, v2, mn, mx):
range_ = v2 - v1
sum_ = np.floor(np.log(calculate_fractal(v1) / range_) / np.log(2))
octave = calculate_fractal(v1) * (0.5 ** sum_)
mn = np.floor(v1 / octave) * octave
if mn + octave > v2:
mx = mn + octave
else:
mx = mn + (2 * octave)
return mx
def calculate_x_values(v1, v2, mn, mx):
dmml = (v2 - v1) / 8
x_values = []
# Calculate the midpoints of each segment
midpoints = [mn + i * dmml for i in range(8)]
for i in range(7):
x_i = (midpoints[i] + midpoints[i + 1]) / 2
x_values.append(x_i)
finalH = max(x_values) # Maximum of the x_values is the finalH
return x_values, finalH
def calculate_y_values(x_values, mn):
y_values = []
for x in x_values:
if x > 0:
y = mn
else:
y = 0
y_values.append(y)
return y_values
def calculate_mml(mn, finalH, mx):
dmml = ((finalH - finalL) / 8) * 1.0699
mml = (float([mx][0]) * 0.99875) + (dmml * 3)
# mml = (float([mx]) * 0.99875) + (dmml * 3)
ml = []
for i in range(0, 16):
calc = mml - (dmml * (i))
ml.append(calc)
murrey_math_levels = {
"[-3/8]P": ml[14],
"[-2/8]P": ml[13],
"[-1/8]P": ml[12],
"[0/8]P": ml[11],
"[1/8]P": ml[10],
"[2/8]P": ml[9],
"[3/8]P": ml[8],
"[4/8]P": ml[7],
"[5/8]P": ml[6],
"[6/8]P": ml[5],
"[7/8]P": ml[4],
"[8/8]P": ml[3],
"[+1/8]P": ml[2],
"[+2/8]P": ml[1],
"[+3/8]P": ml[0]
}
return murrey_math_levels
mn = np.min(min_L)
mx = np.max(max_H)
x_values, finalH = calculate_x_values(mn, mx, mn, mx)
y_values = calculate_y_values(x_values, mn)
finalL = np.min(y_values)
mml = calculate_mml(finalL, finalH, mx)
return mml
class AWATRCT(IStrategy):
INTERFACE_VERSION = 3
# ROI table:
minimal_roi = {
"0": 0.215,
"40": 0.132,
"87": 0.086,
"360": 0.03
}
# Stoploss:
stoploss = -0.318 # -0.042 # -0.318
use_custom_stoploss = True
# SMAOffset
base_nb_candles_buy = IntParameter(20, 60, default=buy_params['base_nb_candles_buy'], space='buy', optimize=True)
base_nb_candles_sell = IntParameter(30, 60, default=sell_params['base_nb_candles_sell'], space='sell', optimize=True)
low_offset = DecimalParameter(0.96, 0.99, default=buy_params['low_offset'], space='buy', decimals=2, optimize=True)
high_offset = DecimalParameter(0.99, 1.04, default=sell_params['high_offset'], decimals=2, space='sell', optimize=True)
fast_ewo = IntParameter(5, 9, default=buy_params['ewof'], space='buy', optimize=True)
fs_ewo = IntParameter(30, 50, default=35, space='buy', optimize=True)
sf_ewo = IntParameter(35, 65, default=50, space='buy', optimize=True)
ss_ewo = IntParameter(180, 200, default=200, space='buy', optimize=True)
slow_ewo = IntParameter(80, 100, default=buy_params['ewos'], space='buy', optimize=True)
ewo_lo_limit = DecimalParameter(-5, 0, default=-2.5, decimals=1, space='buy', optimize=True)
ewo_xo_limit = DecimalParameter(-0.5, 0, default=-0.3, decimals=1, space='buy', optimize=True)
ewo_bear_x = DecimalParameter(1.62, 1.80, default=buy_params['ewo_bear_mult'], decimals=2, space='buy', optimize=True)
ewo_high_x = DecimalParameter(1.30, 1.40, default=buy_params['ewo_high_mult'], decimals=2, space='buy', optimize=True)
ewo_bull_x = DecimalParameter(1.01, 1.3, default=buy_params['ewo_bull_mult'], decimals=3, space='buy', optimize=True)
rsi_buy_low = IntParameter(30, 50, default=35, space='buy', optimize=True)
rsi_buy_high = IntParameter(50, 70, default=buy_params['rsi_buy'], space='buy', optimize=True)
atr_buy = DecimalParameter(0.2, 4, default=1, decimals=1, space='buy', optimize=True)
atr_sell = DecimalParameter(0.2, 4, default=1, decimals=1, space='sell', optimize=True)
### trailing stop loss optimiziation ###
tsl_target5 = DecimalParameter(low=0.2, high=0.4, decimals=1, default=0.3, space='sell', optimize=True, load=True)
ts5 = DecimalParameter(low=0.04, high=0.06, default=0.05, decimals=2,space='sell', optimize=True, load=True)
tsl_target4 = DecimalParameter(low=0.15, high=0.2, default=0.2, decimals=2, space='sell', optimize=True, load=True)
ts4 = DecimalParameter(low=0.03, high=0.05, default=0.045, decimals=2, space='sell', optimize=True, load=True)
tsl_target3 = DecimalParameter(low=0.10, high=0.15, default=0.15, decimals=2, space='sell', optimize=True, load=True)
ts3 = DecimalParameter(low=0.025, high=0.04, default=0.035, decimals=3, space='sell', optimize=True, load=True)
tsl_target2 = DecimalParameter(low=0.06, high=0.10, default=0.1, decimals=3, space='sell', optimize=True, load=True)
ts2 = DecimalParameter(low=0.015, high=0.03, default=0.02, decimals=3, space='sell', optimize=True, load=True)
tsl_target1 = DecimalParameter(low=0.04, high=0.06, default=0.06, decimals=3, space='sell', optimize=True, load=True)
ts1 = DecimalParameter(low=0.01, high=0.016, default=0.013, decimals=3, space='sell', optimize=True, load=True)
tsl_target0 = DecimalParameter(low=0.02, high=0.04, default=0.03, decimals=3, space='sell', optimize=True, load=True)
ts0 = DecimalParameter(low=0.008, high=0.015, default=0.013, decimals=3, space='sell', optimize=True, load=True)
# CooldownPeriod
cooldown_lookback = IntParameter(0, 48, default=5, space="protection", optimize=True)
# StoplossGuard
use_stop_protection = BooleanParameter(default=True, space="protection", optimize=True)
stop_duration = IntParameter(12, 200, default=5, space="protection", optimize=True)
stop_protection_only_per_pair = BooleanParameter(default=False, space="protection", optimize=True)
stop_protection_only_per_side = BooleanParameter(default=False, space="protection", optimize=True)
stop_protection_trade_limit = IntParameter(1, 10, default=4, space="protection", optimize=True)
stop_protection_required_profit = DecimalParameter(-1.0, 3.0, default=0.0, space="protection", optimize=True)
# LowProfitPairs
use_lowprofit_protection = BooleanParameter(default=True, space="protection", optimize=True)
lowprofit_protection_lookback = IntParameter(1, 10, default=6, space="protection", optimize=True)
lowprofit_trade_limit = IntParameter(1, 10, default=4, space="protection", optimize=True)
lowprofit_stop_duration = IntParameter(1, 100, default=60, space="protection", optimize=True)
lowprofit_required_profit = DecimalParameter(-1.0, 3.0, default=0.0, space="protection", optimize=True)
lowprofit_only_per_pair = BooleanParameter(default=False, space="protection", optimize=True)
# MaxDrawdown
use_maxdrawdown_protection = BooleanParameter(default=True, space="protection", optimize=True)
maxdrawdown_protection_lookback = IntParameter(1, 10, default=6, space="protection", optimize=True)
maxdrawdown_trade_limit = IntParameter(1, 20, default=10, space="protection", optimize=True)
maxdrawdown_stop_duration = IntParameter(1, 100, default=6, space="protection", optimize=True)
maxdrawdown_allowed_drawdown = DecimalParameter(0.01, 0.10, default=0.0, space="protection", optimize=True)
# Sell signal
use_sell_signal = True
sell_profit_only = False
sell_profit_offset = 0.01
ignore_roi_if_buy_signal = True
## Optional order time in force.
order_time_in_force = {
'buy': 'gtc',
'sell': 'ioc'
}
# Optimal timeframe for the strategy
timeframe = '15m'
process_only_new_candles = True
startup_candle_count = 89
plot_config = {
'main_plot': {
'ma_buy': {'color': 'orange'},
'ma_sell': {'color': 'orange'},
},
}
@property
def protections(self):
prot = []
prot.append({
"method": "CooldownPeriod",
"stop_duration_candles": self.cooldown_lookback.value
})
if self.use_stop_protection.value:
prot.append({
"method": "StoplossGuard",
"lookback_period_candles": 24 * 3,
"trade_limit": self.stop_protection_trade_limit.value,
"stop_duration_candles": self.stop_duration.value,
"only_per_pair": self.stop_protection_only_per_pair.value,
"required_profit": self.stop_protection_required_profit.value,
"only_per_side": self.stop_protection_only_per_side.value
})
if self.use_lowprofit_protection.value:
prot.append({
"method": "LowProfitPairs",
"lookback_period_candles": self.lowprofit_protection_lookback.value,
"trade_limit": self.lowprofit_trade_limit.value,
"stop_duration_candles": self.lowprofit_stop_duration.value,
"required_profit": self.lowprofit_required_profit.value,
"only_per_pair": self.lowprofit_only_per_pair.value
})
if self.use_maxdrawdown_protection.value:
prot.append({
"method": "MaxDrawdown",
"lookback_period_candles": self.maxdrawdown_protection_lookback.value,
"trade_limit": self.maxdrawdown_trade_limit.value,
"stop_duration_candles": self.maxdrawdown_stop_duration.value,
"max_allowed_drawdown": self.maxdrawdown_allowed_drawdown.value
})
return prot
### Trailing Stop ###
def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
current_rate: float, current_profit: float, **kwargs) -> float:
dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
current_candle = dataframe.iloc[-1].squeeze()
if current_candle['rsi'] < 80:
for stop5 in self.tsl_target5.range:
if (current_profit > stop5):
for stop5a in self.ts5.range:
self.dp.send_msg(f'*** {pair} *** Profit: {current_profit} - lvl5 {stop5}/{stop5a} activated')
return stop5a
for stop4 in self.tsl_target4.range:
if (current_profit > stop4):
for stop4a in self.ts4.range:
self.dp.send_msg(f'*** {pair} *** Profit {current_profit} - lvl4 {stop4}/{stop4a} activated')
return stop4a
for stop3 in self.tsl_target3.range:
if (current_profit > stop3):
for stop3a in self.ts3.range:
self.dp.send_msg(f'*** {pair} *** Profit {current_profit} - lvl3 {stop3}/{stop3a} activated')
return stop3a
for stop2 in self.tsl_target2.range:
if (current_profit > stop2):
for stop2a in self.ts2.range:
self.dp.send_msg(f'*** {pair} *** Profit {current_profit} - lvl2 {stop2}/{stop2a} activated')
return stop2a
for stop1 in self.tsl_target1.range:
if (current_profit > stop1):
for stop1a in self.ts1.range:
self.dp.send_msg(f'*** {pair} *** Profit {current_profit} - lvl1 {stop1}/{stop1a} activated')
return stop1a
for stop0 in self.tsl_target0.range:
if (current_profit > stop0):
for stop0a in self.ts0.range:
self.dp.send_msg(f'*** {pair} *** Profit {current_profit} - lvl0 {stop0}/{stop0a} activated')
return stop0a
else:
for stop0 in self.tsl_target0.range:
if (current_profit > stop0):
self.dp.send_msg(f'*** {pair} *** Profit {current_profit} SWINGING FOR THE MOON!!!')
return 0.99
return self.stoploss
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# Calculate all ma_buy values
for val in self.base_nb_candles_buy.range:
dataframe[f'ma_buy_{val}'] = ta.EMA(dataframe, timeperiod=val)
# Calculate all ma_sell values
for val in self.base_nb_candles_sell.range:
dataframe[f'ma_sell_{val}'] = ta.EMA(dataframe, timeperiod=val)
# Elliot
dataframe['EWO'] = EWO(dataframe, self.fast_ewo, self.slow_ewo)
dataframe['FEWO'] = EWO(dataframe, self.fast_ewo, self.fs_ewo)
dataframe['SEWO'] = EWO(dataframe, self.sf_ewo, self.ss_ewo)
dataframe['EWO_DIF'] = dataframe['FEWO'] - dataframe['SEWO']
# EMAs for Bear/Bull
dataframe['ema'] = ta.EMA(dataframe, timeperiod=self.fast_ewo.value)
dataframe['ema2'] = ta.EMA(dataframe, timeperiod=self.slow_ewo.value)
# RSI
dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14) # 14)
dataframe['rsi_ma'] = ta.SMA(dataframe['rsi'], timeperiod=10) # 5)
# absolute ewo
dataframe["ABSEWO"] = dataframe["EWO"]
dataframe.loc[dataframe["EWO"] < 0, "ABSEWO"] = dataframe["EWO"] * - 1
# seperate pos and neg ewo
dataframe.loc[dataframe["EWO"] > 0, "POSEWO"] = dataframe["EWO"]
dataframe.loc[dataframe["EWO"] < 0, "NEGEWO"] = dataframe["EWO"]
dataframe["POSEWO"].fillna(method="ffill", inplace=True)
dataframe["NEGEWO"].fillna(method="ffill", inplace=True)
# angle of the ema
candlesBack = 3
backQuote = dataframe['ema'].shift(candlesBack)
deltaX = candlesBack
deltaY = dataframe['ema'] - backQuote
dataframe['angleRad'] = (deltaY / deltaX).apply(lambda x: math.atan(x))
dataframe['angle_perc'] = (dataframe['angleRad'] / dataframe['close']) * 100
threshold = 0 # .0000001
dataframe["ema_angle_up"] = dataframe['angleRad'] > 0 + threshold
dataframe["ema_angle_down"] = dataframe['angleRad'] < 0 - threshold
# ewo normalized
dataframe['min'] = dataframe["EWO"].expanding(self.slow_ewo.value).min()
dataframe['max'] = dataframe["EWO"].expanding(self.slow_ewo.value).max()
dataframe['dif'] = dataframe['max'].sub(dataframe['min'])
dataframe["ewoNorm"] = dataframe["EWO"] / dataframe['dif']
dataframe['ewoNormMa'] = ta.SMA(dataframe["ewoNorm"], timeperiod=self.fast_ewo.value)
dataframe['ewoNormMaHigh'] = 0.0618
# angle of the ewoNorm
candlesBack2 = 1
backQuote2 = dataframe['ewoNorm'].shift(candlesBack2)
deltaX2 = candlesBack2
deltaY2 = dataframe['ewoNorm'] - backQuote2
dataframe['ewoAngleRad'] = (deltaY2 / deltaX2).apply(lambda x: math.atan(x))
dataframe["ewo_angle_up"] = dataframe['ewoAngleRad'] > -0.0001
dataframe["ewo_angle_down"] = dataframe['ewoAngleRad'] < 0.0001
emaPercent = dataframe['ema'] / dataframe['ema2']
avg_positive_ewo = dataframe["POSEWO"].rolling(self.slow_ewo.value).mean()
avg_negative_ewo = dataframe["NEGEWO"].rolling(self.slow_ewo.value).mean()
avg_abs_ewo = dataframe["ABSEWO"].rolling(self.slow_ewo.value).mean()
# scale the buys. if we bear then push back the buys if we bull make more buys
dataframe["ewo_low_mult"] = self.ewo_bull_x.value # / emaPercent # 0.618
dataframe.loc[dataframe["ema"] < dataframe["ema2"], "ewo_low_mult"] = self.ewo_bear_x.value
# for buy below rolling ewo low
ewo_low = avg_negative_ewo * dataframe["ewo_low_mult"]
dataframe['ewo_low'] = ewo_low
# for rsi buy
ewo_high = avg_positive_ewo * self.ewo_high_x.value
dataframe['ewo_high'] = ewo_high
dataframe['ewo_limit'] = self.ewo_lo_limit.value
#ATR active MA Offset adjustments
dataframe['atr_pcnt'] = (qtpylib.atr(dataframe, window=5) / (dataframe['close'] + dataframe['open'] / 2))
dataframe['atr_buy'] = dataframe['atr_pcnt'] / self.atr_buy.value
dataframe['atr_sell'] = dataframe['atr_pcnt'] / self.atr_sell.value
dataframe['ma_lo'] = dataframe[f'ma_buy_{self.base_nb_candles_buy.value}'] * (self.low_offset.value - (dataframe['atr_buy']))
dataframe['ma_hi'] = dataframe[f'ma_buy_{self.base_nb_candles_buy.value}'] * (self.high_offset.value + (dataframe['atr_sell']))
dataframe['lo_average'] = dataframe['ewo_low'].expanding().mean()
dataframe['hi_average'] = dataframe['ewo_high'].expanding().mean()
dataframe['min_of_mins'] = dataframe['ewo_low'].expanding(self.slow_ewo.value).min()
dataframe['max_of_mins'] = dataframe['ewo_low'].expanding(self.slow_ewo.value).max()
dataframe['min_of_maxs'] = dataframe['ewo_high'].expanding(self.slow_ewo.value).min()
dataframe['max_of_maxs'] = dataframe['ewo_high'].expanding(self.slow_ewo.value).max()
murrey_math_levels = calculate_murrey_math_levels(dataframe)
for level, value in murrey_math_levels.items():
dataframe[level] = value
# Track Order Book Depth
ob = self.dp.orderbook(metadata['pair'], 100)
levels = [0.005, 0.01, 0.02, 0.03, 0.04, 0.05]
df = pd.DataFrame(ob['asks'], columns=['price', 'volume'])
df['mid_price'] = (ob['bids'][0][0] + ob['asks'][0][0]) / 2
seller_data = []
seller_df = pd.DataFrame(columns=['level', 'total_volume', 'average_price'])
for level in levels:
upper_bound = df['mid_price'] * (1 + level)
lower_bound = df['mid_price'] * (1 - level)
within_level = df[(df['price'] <= upper_bound) & (df['price'] >= lower_bound)]
total_volume = within_level['volume'].sum()
if total_volume > 0:
average_price = (within_level['volume'] * within_level['price']).sum() / total_volume
else:
average_price = 0 # Set to 0 if no prices within the level
seller_data.append({'level': level, 'total_volume': total_volume, 'average_price': average_price})
seller_df = pd.DataFrame(seller_data)
for level in levels:
column_name = f'{level}_TV'
total_volume = seller_df[seller_df['level'] == level]['total_volume'].values[0]
most_recent_row_index = dataframe.index[-1]
dataframe.at[most_recent_row_index, column_name] = total_volume
df = pd.DataFrame(ob['bids'], columns=['price', 'volume'])
df['mid_price'] = (ob['bids'][0][0] + ob['asks'][0][0]) / 2
# levels = [-0.005, -0.01, -0.02, -0.03, -0.04, -0.05]
buyer_data = []
buyer_df = pd.DataFrame(columns=['level', 'total_volume', 'average_price'])
for level in levels:
upper_bound = df['mid_price'] * (1 + level)
lower_bound = df['mid_price'] * (1 - level)
within_level = df[(df['price'] <= upper_bound) & (df['price'] >= lower_bound)]
total_volume = within_level['volume'].sum()
if total_volume > 0:
average_price = (within_level['volume'] * within_level['price']).sum() / total_volume
else:
average_price = 0 # Set to 0 if no prices within the level
buyer_data.append({'level': level, 'total_volume': total_volume, 'average_price': average_price})
buyer_df = pd.DataFrame(buyer_data)
for level in levels:
column_name = f'-{level}_TV'
total_volume = buyer_df[buyer_df['level'] == level]['total_volume'].values[0]
most_recent_row_index = dataframe.index[-1]
dataframe.at[most_recent_row_index, column_name] = -total_volume
return dataframe
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
proposed_stake: float, min_stake: Optional[float], max_stake: float,
leverage: float, entry_tag: Optional[str], side: str,
**kwargs) -> float:
dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
current_candle = dataframe.iloc[-1].squeeze()
if current_candle['rsi'] < 40:
self.dp.send_msg("Deploying Maximum Capital")
if self.config['stake_amount'] == 'unlimited':
# Use entire available wallet during favorable conditions when in compounding mode.
return self.wallets.get_total_stake_amount() / self.config['max_open_trades']
else:
# Compound profits during favorable conditions instead of using a static stake.
return self.wallets.get_total_stake_amount() / self.config['max_open_trades']
else:
self.dp.send_msg(f"Capital Conservation Mode Enabled for {pair}")
return (self.wallets.get_total_stake_amount() / 1.5) / self.config['max_open_trades']
print("PROPOSED STAKE:::::::::::::::::::::::::::::::::::::::::::::::")
print(proposed_stake, pair)
# Use default stake amount.
return proposed_stake
def populate_buy_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
df.loc[
(
(df['EWO'] < df['ewo_high']) &
(df['close'] < df['ma_lo']) &
(df["ewo_angle_up"]) &
(df['volume'] > 0) # Make sure Volume is not 0
),
['enter_long', 'enter_tag']] = (1, 'EWO < HIGH')
# df.loc[
# (
# (qtpylib.crossed_above(df['EWO'], df['hi_average'])) &
# # (df['close'] < df['ma_lo']) &
# # (df["ewo_angle_up"]) &
# (df['rsi'] < self.rsi_buy_high.value) &
# (df['volume'] > 0) # Make sure Volume is not 0
# ),
# ['enter_long', 'enter_tag']] = (1, 'EWO XO HIGH')
df.loc[
(
(qtpylib.crossed_above(df['EWO'], df['ewo_low'])) &
(df['close'] < df['ma_lo']) &
(df['EWO'] < self.ewo_lo_limit.value) &
(df['rsi'] < self.rsi_buy_low.value) &
(df['[2/8]P'] > df['close']) &
(df['volume'] > 0) # Make sure Volume is not 0
),
['enter_long', 'enter_tag']] = (1, 'EWO XO LOW')
df.loc[
(
(df['EWO'] < df['ewo_low']) &
(df['close'] < df['ma_lo']) &
(df['EWO'] < self.ewo_lo_limit.value) &
(df['rsi'] < self.rsi_buy_low.value) &
(df['[2/8]P'] > df['close']) &
(df['volume'] > 0) # Make sure Volume is not 0
),
['enter_long', 'enter_tag']] = (1, 'EWO < LOW')
df.loc[
(
((df['angle_perc'] - df['angle_perc'].shift(1)) > 0.07 ) &
((df['angle_perc'].shift(1) - df['angle_perc'].shift(2)) < 0 ) &
(df['angle_perc'] < 0) &
(df['[2/8]P'] > df['close']) &
(df['open'] < (df[f'ma_buy_{self.base_nb_candles_buy.value}'] * self.low_offset.value)) &
(df['volume'] > 0) # Make sure Volume is not 0
),
['enter_long', 'enter_tag']] = (1, 'Angle Change Neg')
return df
def populate_sell_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
df.loc[
(
# (df['close'].shift() > df['ma_hi']) &
(df['close'] > df['ma_hi']) &
(df['EWO'] > df['ewo_high']) &
(df['rsi'] <= df['rsi_ma']) &
(df['EWO'] > 0) &
(df['volume'] > 0) # Make sure Volume is not 0
),
['exit_long', 'exit_tag']] = (1, 'EWO High')
df.loc[
(
(df['close'] > df['ma_hi']) &
(df['rsi'] >= 89) &
(df['EWO'] > 0) &
(df['volume'] > 0) # Make sure Volume is not 0
),
['exit_long', 'exit_tag']] = (1, 'EWO rsi limit')
df.loc[
(
(df['close'] > df['ma_hi']) &
(df['rsi'] >= 89) &
(df['EWO'] < 0) &
(df['volume'] > 0) # Make sure Volume is not 0
),
['exit_long', 'exit_tag']] = (1, 'EWO low rsi limit')
return df
# "0": 0.202,
# "141": 0.094,
# "380": 0.017,
# "1459": 0
# "pair_whitelist": [
# "ATOM/USDT",
# "XRP/USDT",
# "QNT/USDT",
# "AKT/USDT",
# "IOTA/USDT",
# "ADA/USDT",
# "OSMO/USDT",
# "BTC/USDT",
# "ETH/USDT",
# "CSPR/USDT",
# "ETC/USDT",
# "XDC/USDT",
# "LINK/USDT",
# "MATIC/USDT",
# "AVAX/USDT",
# "HBAR/USDT",
# "SCRT/USDT",
# "KAVA/USDT",
# "INJ/USDT",
# "NEAR/USDT",
# "DOT/USDT",
# "ALGO/USDT",
# "XLM/USDT",
# "RNDR/USDT",
# "ORAI/USDT",
# "AGIX/USDT",
# "GRT/USDT",
# "DOGE/USDT",
# "SOL/USDT",
# "TRX/USDT",
# "UNI/USDT",
# "LDO/USDT",
# "FIL/USDT",
# "VET/USDT",
# "EGLD/USDT",
# "THETA/USDT",
# "XTZ/USDT",
# "IMX/USDT",
# "ZEC/USDT",
# "GMX/USDT",
# "KLAY/USDT",
# "OP/USDT",
# "ROSE/USDT",
# "ENJ/USDT",
# "DYDX/USDT",
# "OCEAN/USDT",
# "FLR/USDT",
# "EWT/USDT",
# "JASMY/USDT",
# "APT/USDT",
# "APE/USDT",
# "EOS/USDT",
# "LUNC/USDT",
# "ANKR/USDT",
# "GALAX/USDT",
# "OPUL/USDT",
# "FET/USDT",
# "FTM/USDT",
# "EOSC/USDT",
# "VELO/USDT",
# "YFDAI/USDT",
# "BAT/USDT",
# "TRU/USDT",
# "YFI/USDT",
# "COMP/USDT",
# "AGLD/USDT",
# "SUSHI/USDT",
# "RLY/USDT",
# "CTI/USDT",
# 164/1000: 230 trades. 145/1/84 Wins/Draws/Losses. Avg profit 0.44%. Median profit 0.63%. Total profit 501.08426833 USDT ( 50.11%). Avg duration 7:29:00 min. Objective: -487.66331
# # Buy hyperspace params:
# buy_params = {
# "atr_buy": 2, # value loaded from strategy
# "base_nb_candles_buy": 20, # value loaded from strategy
# "ewo_bear_x": 1.62, # value loaded from strategy
# "ewo_bull_x": 1.143, # value loaded from strategy
# "ewo_high_x": 1.39, # value loaded from strategy
# "ewo_lo_limit": -1.9, # value loaded from strategy
# "fast_ewo": 7, # value loaded from strategy
# "low_offset": 0.99, # value loaded from strategy
# "rsi_buy_high": 70, # value loaded from strategy
# "rsi_buy_low": 48, # value loaded from strategy
# "slow_ewo": 96, # value loaded from strategy
# }
# # Sell hyperspace params:
# sell_params = {
# "atr_sell": 2, # value loaded from strategy
# "base_nb_candles_sell": 39, # value loaded from strategy
# "high_offset": 0.99, # value loaded from strategy
# "ts0": 0.008, # value loaded from strategy
# "ts1": 0.01, # value loaded from strategy
# "ts2": 0.02, # value loaded from strategy
# "ts3": 0.04, # value loaded from strategy
# "ts4": 0.05, # value loaded from strategy
# "ts5": 0.04, # value loaded from strategy
# "tsl_target0": 0.038, # value loaded from strategy
# "tsl_target1": 0.048, # value loaded from strategy
# "tsl_target2": 0.092, # value loaded from strategy
# "tsl_target3": 0.14, # value loaded from strategy
# "tsl_target4": 0.18, # value loaded from strategy
# "tsl_target5": 0.2, # value loaded from strategy
# }
# # Protection hyperspace params:
# protection_params = {
# "cooldown_lookback": 16,
# "lowprofit_only_per_pair": False,
# "lowprofit_protection_lookback": 5,
# "lowprofit_required_profit": 0.146,
# "lowprofit_stop_duration": 54,
# "lowprofit_trade_limit": 1,
# "maxdrawdown_allowed_drawdown": 0.074,
# "maxdrawdown_protection_lookback": 1,
# "maxdrawdown_stop_duration": 82,
# "maxdrawdown_trade_limit": 15,
# "stop_duration": 38,
# "stop_protection_only_per_pair": False,
# "stop_protection_only_per_side": True,
# "stop_protection_required_profit": 0.082,
# "stop_protection_trade_limit": 1,
# "use_lowprofit_protection": True,
# "use_maxdrawdown_protection": False,
# "use_stop_protection": True,
# }
# # ROI table:
# minimal_roi = {
# "0": 0.144,
# "131": 0.087,
# "582": 0.053,
# "1511": 0
# }
# # Stoploss:
# stoploss = -0.14
# # Trailing stop:
# trailing_stop = False # value loaded from strategy
# trailing_stop_positive = None # value loaded from strategy
# trailing_stop_positive_offset = 0.0 # value loaded from strategy
# trailing_only_offset_is_reached = False # value loaded from strategy