0% found this document useful (0 votes)
101 views23 pages

JH

The document outlines a trading strategy implemented in Python using the Freqtrade framework, incorporating various technical indicators such as EMA, Williams %R, and Chaikin Money Flow. It defines parameters for buying and selling, including conditions for entry and exit signals, as well as optimization settings for strategy performance. The strategy aims to maximize profit while managing risk through stop-loss and trailing stop settings.

Uploaded by

kdaaadda
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
101 views23 pages

JH

The document outlines a trading strategy implemented in Python using the Freqtrade framework, incorporating various technical indicators such as EMA, Williams %R, and Chaikin Money Flow. It defines parameters for buying and selling, including conditions for entry and exit signals, as well as optimization settings for strategy performance. The strategy aims to maximize profit while managing risk through stop-loss and trailing stop settings.

Uploaded by

kdaaadda
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

import [Link].

indicators as qtpylib
import numpy as np
from functools import reduce
import [Link] as ta
from [Link] import IStrategy
from [Link] import merge_informative_pair, DecimalParameter,
stoploss_from_open, RealParameter,IntParameter,informative
from pandas import DataFrame, Series
from datetime import datetime
import math
import logging
from [Link] import Trade
import pandas_ta as pta
from [Link] import RMI

logger = [Link](__name__)

def ewo(dataframe, sma1_length=5, sma2_length=35):


sma1 = [Link](dataframe, timeperiod=sma1_length)
sma2 = [Link](dataframe, timeperiod=sma2_length)
smadif = (sma1 - sma2) / dataframe['close'] * 100
return smadif

def top_percent_change_dca(dataframe: DataFrame, length: int) -> float:


"""
Percentage change of the current close from the range maximum Open price

:param dataframe: DataFrame The original OHLC dataframe


:param length: int The length to look back
"""
if length == 0:
return (dataframe['open'] - dataframe['close']) / dataframe['close']
else:
return (dataframe['open'].rolling(length).max() - dataframe['close']) /
dataframe['close']

def EWO(dataframe, ema_length=5, ema2_length=3):


df = [Link]()
ema1 = [Link](df, timeperiod=ema_length)
ema2 = [Link](df, timeperiod=ema2_length)
emadif = (ema1 - ema2) / df['close'] * 100
return emadif

def williams_r(dataframe: DataFrame, period: int = 14) -> Series:


"""Williams %R, or just %R, is a technical analysis oscillator showing the
current closing price in relation to the high and low
of the past N days (for a given N). It was developed by a publisher and
promoter of trading materials, Larry Williams.
Its purpose is to tell whether a stock or commodity market is trading near
the high or the low, or somewhere in between,
of its recent trading range.
The oscillator is on a negative scale, from −100 (lowest) up to 0
(highest).
"""

highest_high = dataframe["high"].rolling(center=False, window=period).max()


lowest_low = dataframe["low"].rolling(center=False, window=period).min()

WR = Series(
(highest_high - dataframe["close"]) / (highest_high - lowest_low),
name="{0} Williams %R".format(period),
)

return WR * -100

def VWAPB(dataframe, window_size=20, num_of_std=1):


df = [Link]()
df['vwap'] = qtpylib.rolling_vwap(df,window=window_size)
rolling_std = df['vwap'].rolling(window=window_size).std()
df['vwap_low'] = df['vwap'] - (rolling_std * num_of_std)
df['vwap_high'] = df['vwap'] + (rolling_std * num_of_std)
return df['vwap_low'], df['vwap'], df['vwap_high']

def bollinger_bands(stock_price, window_size, num_of_std):


rolling_mean = stock_price.rolling(window=window_size).mean()
rolling_std = stock_price.rolling(window=window_size).std()
lower_band = rolling_mean - (rolling_std * num_of_std)
return np.nan_to_num(rolling_mean), np.nan_to_num(lower_band)

def chaikin_money_flow(dataframe, n=20, fillna=False) -> Series:


"""Chaikin Money Flow (CMF)
It measures the amount of Money Flow Volume over a specific period.
[Link]
id=chart_school:technical_indicators:chaikin_money_flow_cmf
Args:
dataframe([Link]): dataframe containing ohlcv
n(int): n period.
fillna(bool): if True, fill nan values.
Returns:
[Link]: New feature generated.
"""
mfv = ((dataframe['close'] - dataframe['low']) - (dataframe['high'] -
dataframe['close'])) / (dataframe['high'] - dataframe['low'])
mfv = [Link](0.0) # float division by zero
mfv *= dataframe['volume']
cmf = ([Link](n, min_periods=0).sum()
/ dataframe['volume'].rolling(n, min_periods=0).sum())
if fillna:
cmf = [Link]([[Link], -[Link]], [Link]).fillna(0)
return Series(cmf, name='cmf')

def ha_typical_price(bars):
res = (bars['ha_high'] + bars['ha_low'] + bars['ha_close']) / 3.
return Series(index=[Link], data=res)

class newstrategy_modify_support_ft(IStrategy):
"""
PASTE OUTPUT FROM HYPEROPT HERE
Can be overridden for specific sub-strategies (stake currencies) at the bottom.
MaxDrawDownRelativeHyperOptLoss
31/900: 801 trades. 800/0/1 Wins/Draws/Losses. Avg profit 4.04%. Median
profit 3.70%. Total profit 57.02887841 USDT ( 5.70%). Avg duration [Link] min.
Objective: -14799833083.36105
"""

can_short=True
buy_params = {
"bbdelta_close": 0.00082,
"bbdelta_tail": 0.85788,
"close_bblower": 0.00128,
"closedelta_close": 0.00987,
"low_offset": 0.991,
"rocr1_1h": 0.9346,
"rocr_1h": 0.65666,
"base_nb_candles_buy": 12, # value loaded from strategy
"buy_bb_delta": 0.025, # value loaded from strategy
"buy_bb_factor": 0.995, # value loaded from strategy
"buy_bb_width": 0.095, # value loaded from strategy
"buy_bb_width_1h": 1.074, # value loaded from strategy
"buy_cci": -116, # value loaded from strategy
"buy_cci_length": 25, # value loaded from strategy
"buy_closedelta": 15.0, # value loaded from strategy
"buy_clucha_bbdelta_close": 0.049, # value loaded from strategy
"buy_clucha_bbdelta_tail": 1.146, # value loaded from strategy
"buy_clucha_close_bblower": 0.018, # value loaded from strategy
"buy_clucha_closedelta_close": 0.017, # value loaded from strategy
"buy_clucha_rocr_1h": 0.526, # value loaded from strategy
"buy_ema_diff": 0.025, # value loaded from strategy
"buy_rmi": 49, # value loaded from strategy
"buy_rmi_length": 17, # value loaded from strategy
"buy_roc_1h": 10, # value loaded from strategy
"buy_srsi_fk": 32, # value loaded from strategy
}

sell_params = {
"high_offset": 1.012,
"high_offset_2": 1.016,
"sell_deadfish_bb_factor": 1.089,
"sell_deadfish_bb_width": 0.11,
"sell_deadfish_profit": -0.107,
"sell_deadfish_volume_factor": 1.761,
"base_nb_candles_sell": 22, # value loaded from strategy
"pHSL": -0.397, # value loaded from strategy
"pPF_1": 0.012, # value loaded from strategy
"pPF_2": 0.07, # value loaded from strategy
"pSL_1": 0.015, # value loaded from strategy
"pSL_2": 0.068, # value loaded from strategy
"sell_bbmiddle_close": 1.09092, # value loaded from strategy
"sell_fisher": 0.46406, # value loaded from strategy
"sell_trail_down_1": 0.03, # value loaded from strategy
"sell_trail_down_2": 0.015, # value loaded from strategy
"sell_trail_profit_max_1": 0.4, # value loaded from strategy
"sell_trail_profit_max_2": 0.11, # value loaded from strategy
"sell_trail_profit_min_1": 0.1, # value loaded from strategy
"sell_trail_profit_min_2": 0.04, # value loaded from strategy
}

minimal_roi = {
"0": 0.276,
"32": 0.105,
"88": 0.037,
"208": 0
}

position_adjustment_enable = True

stoploss = -0.99 # use custom stoploss

trailing_stop = False
trailing_stop_positive = 0.02 #povodne 0.001
trailing_stop_positive_offset = 0.10 #povodne 0.012
trailing_only_offset_is_reached = True

"""
END HYPEROPT
"""

timeframe = '5m'

use_exit_signal = True
exit_profit_only = False
ignore_roi_if_entry_signal = False

use_custom_stoploss = False

process_only_new_candles = True
startup_candle_count = 168

order_types = {
'entry': 'market',
'exit': 'market',
'stoploss': 'market',
'stoploss_on_exchange': False,
}

def is_support(self, row_data) -> bool:


conditions = []
for row in range(len(row_data)-1):
if row < len(row_data)/2:
[Link](row_data[row] > row_data[row+1])
else:
[Link](row_data[row] < row_data[row+1])
return reduce(lambda x, y: x & y, conditions)

fast_ewo = 50
slow_ewo = 200

buy_44_ma_offset = 0.982
buy_44_ewo = -18.143
buy_44_cti = -0.8
buy_44_r_1h = -75.0

buy_37_ma_offset = 0.98
buy_37_ewo = 9.8
buy_37_rsi = 56.0
buy_37_cti = -0.7

buy_ema_open_mult_7 = 0.030
buy_cti_7 = -0.89
is_optimize_dip = False
buy_rmi = IntParameter(30, 50, default=35, optimize= is_optimize_dip)
buy_cci = IntParameter(-135, -90, default=-133, optimize= is_optimize_dip)
buy_srsi_fk = IntParameter(30, 50, default=25, optimize= is_optimize_dip)
buy_cci_length = IntParameter(25, 45, default=25, optimize = is_optimize_dip)
buy_rmi_length = IntParameter(8, 20, default=8, optimize = is_optimize_dip)

is_optimize_break = False
buy_bb_width = DecimalParameter(0.065, 0.135, default=0.095, optimize =
is_optimize_break)
buy_bb_delta = DecimalParameter(0.018, 0.035, default=0.025, optimize =
is_optimize_break)

is_optimize_check = False
buy_roc_1h = IntParameter(-25, 200, default=10, optimize = is_optimize_check)
buy_bb_width_1h = DecimalParameter(0.3, 2.0, default=0.3, optimize =
is_optimize_check)

is_optimize_clucha = False
buy_clucha_bbdelta_close = DecimalParameter(0.01,0.05, default=0.02206,
optimize=is_optimize_clucha)
buy_clucha_bbdelta_tail = DecimalParameter(0.7, 1.2, default=1.02515,
optimize=is_optimize_clucha)
buy_clucha_close_bblower = DecimalParameter(0.001, 0.05, default=0.03669,
optimize=is_optimize_clucha)
buy_clucha_closedelta_close = DecimalParameter(0.001, 0.05, default=0.04401,
optimize=is_optimize_clucha)
buy_clucha_rocr_1h = DecimalParameter(0.1, 1.0, default=0.47782,
optimize=is_optimize_clucha)

is_optimize_local_uptrend = False
buy_ema_diff = DecimalParameter(0.022, 0.027, default=0.025, optimize =
is_optimize_local_uptrend)
buy_bb_factor = DecimalParameter(0.990, 0.999, default=0.995, optimize = False)
buy_closedelta = DecimalParameter(12.0, 18.0, default=15.0, optimize =
is_optimize_local_uptrend)

rocr_1h = RealParameter(0.5, 1.0, default=0.54904, space='buy', optimize=True)


rocr1_1h = RealParameter(0.5, 1.0, default=0.72, space='buy', optimize=True)
bbdelta_close = RealParameter(0.0005, 0.02, default=0.01965, space='buy',
optimize=True)
closedelta_close = RealParameter(0.0005, 0.02, default=0.00556, space='buy',
optimize=True)
bbdelta_tail = RealParameter(0.7, 1.0, default=0.95089, space='buy',
optimize=True)
close_bblower = RealParameter(0.0005, 0.02, default=0.00799, space='buy',
optimize=True)

sell_fisher = RealParameter(0.1, 0.5, default=0.38414, space='sell',


optimize=False)
sell_bbmiddle_close = RealParameter(0.97, 1.1, default=1.07634, space='sell',
optimize=False)

is_optimize_deadfish = True
sell_deadfish_bb_width = DecimalParameter(0.03, 0.75, default=0.05 ,
space='sell', optimize = is_optimize_deadfish)
sell_deadfish_profit = DecimalParameter(-0.15, -0.05, default=-0.08 ,
space='sell', optimize = is_optimize_deadfish)
sell_deadfish_bb_factor = DecimalParameter(0.90, 1.20, default=1.0 ,
space='sell', optimize = is_optimize_deadfish)
sell_deadfish_volume_factor = DecimalParameter(1, 2.5,
default=1.5 ,space='sell', optimize = is_optimize_deadfish)

base_nb_candles_buy = IntParameter(8, 20,


default=buy_params['base_nb_candles_buy'], space='buy', optimize=False)
base_nb_candles_sell = IntParameter(8, 20,
default=sell_params['base_nb_candles_sell'], space='sell', optimize=False)
low_offset = DecimalParameter(0.985, 0.995, default=buy_params['low_offset'],
space='buy', optimize=True)
high_offset = DecimalParameter(1.005, 1.015,
default=sell_params['high_offset'], space='sell', optimize=True)
high_offset_2 = DecimalParameter(1.010, 1.020,
default=sell_params['high_offset_2'], space='sell', optimize=True)

sell_trail_profit_min_1 = DecimalParameter(0.1, 0.25, default=0.1,


space='sell', decimals=3, optimize=False, load=True)
sell_trail_profit_max_1 = DecimalParameter(0.3, 0.5, default=0.4, space='sell',
decimals=2, optimize=False, load=True)
sell_trail_down_1 = DecimalParameter(0.04, 0.1, default=0.03, space='sell',
decimals=3, optimize=False, load=True)

sell_trail_profit_min_2 = DecimalParameter(0.04, 0.1, default=0.04,


space='sell', decimals=3, optimize=False, load=True)
sell_trail_profit_max_2 = DecimalParameter(0.08, 0.25, default=0.11,
space='sell', decimals=2, optimize=False, load=True)
sell_trail_down_2 = DecimalParameter(0.04, 0.2, default=0.015, space='sell',
decimals=3, optimize=False, load=True)

pHSL = DecimalParameter(-0.500, -0.040, default=-0.08, decimals=3,


space='sell', optimize=False, load=True)

pPF_1 = DecimalParameter(0.008, 0.020, default=0.016, decimals=3, space='sell',


optimize=False, load=True)
pSL_1 = DecimalParameter(0.008, 0.020, default=0.011, decimals=3, space='sell',
optimize=False, load=True)

pPF_2 = DecimalParameter(0.040, 0.100, default=0.080, decimals=3,


space='sell',optimize=False, load=True)
pSL_2 = DecimalParameter(0.020, 0.070, default=0.040, decimals=3, space='sell',
optimize=False,load=True)

def informative_pairs(self):
pairs = [Link].current_whitelist()
informative_pairs = [(pair, '1h') for pair in pairs]
return informative_pairs

def custom_exit(self, pair: str, trade: 'Trade', current_time: 'datetime',


current_rate: float, current_profit: float, **kwargs):
dataframe, _ = [Link].get_analyzed_dataframe(pair, [Link])
last_candle = [Link][-1].squeeze()
filled_buys = trade.select_filled_orders('buy')
count_of_buys = len(filled_buys)

if (last_candle is not None):

if (current_profit > self.sell_trail_profit_min_1.value) &


(current_profit < self.sell_trail_profit_max_1.value) & (((trade.max_rate -
trade.open_rate) / 100) > (current_profit + self.sell_trail_down_1.value)):
return 'trail_target_1'
elif (current_profit > self.sell_trail_profit_min_2.value) &
(current_profit < self.sell_trail_profit_max_2.value) & (((trade.max_rate -
trade.open_rate) / 100) > (current_profit + self.sell_trail_down_2.value)):
return 'trail_target_2'
elif (current_profit > 3) & (last_candle['rsi'] > 85):
return 'RSI-85 target'

if (current_profit > 0) & (count_of_buys < 4) & (last_candle['close'] >


last_candle['hma_50']) & (last_candle['close'] >
(last_candle[f'ma_sell_{self.base_nb_candles_sell.value}'] *
self.high_offset_2.value)) & (last_candle['rsi']>50) & (last_candle['volume'] > 0)
& (last_candle['rsi_fast'] > last_candle['rsi_slow']):
return 'sell signal1'
if (current_profit > 0) & (count_of_buys >= 4) & (last_candle['close']
> last_candle['hma_50'] * 1.01) & (last_candle['close'] >
(last_candle[f'ma_sell_{self.base_nb_candles_sell.value}'] *
self.high_offset_2.value)) & (last_candle['rsi']>50) & (last_candle['volume'] > 0)
& (last_candle['rsi_fast'] > last_candle['rsi_slow']):
return 'sell signal1 * 1.01'
if (current_profit > 0) & (last_candle['close'] >
last_candle['hma_50']) & (last_candle['close'] >
(last_candle[f'ma_sell_{self.base_nb_candles_sell.value}'] *
self.high_offset.value)) & (last_candle['volume'] > 0) & (last_candle['rsi_fast']
> last_candle['rsi_slow']):
return 'sell signal2'

return 'sell stoploss1'

if ( (current_profit < self.sell_deadfish_profit.value)


and (last_candle['close'] < last_candle['ema_200'])
and (last_candle['bb_width'] < self.sell_deadfish_bb_width.value)
and (last_candle['close'] > last_candle['bb_middleband2'] *
self.sell_deadfish_bb_factor.value)
and (last_candle['volume_mean_12'] < last_candle['volume_mean_24']
* self.sell_deadfish_volume_factor.value)
and (last_candle['cmf'] < 0.0)
):
return f"sell_stoploss_deadfish"

def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,


current_rate: float, current_profit: float, **kwargs) ->
float:

HSL = [Link]
PF_1 = self.pPF_1.value
SL_1 = self.pSL_1.value
PF_2 = self.pPF_2.value
SL_2 = self.pSL_2.value

if current_profit > PF_2:


sl_profit = SL_2 + (current_profit - PF_2)
elif current_profit > PF_1:
sl_profit = SL_1 + ((current_profit - PF_1) * (SL_2 - SL_1) / (PF_2 -
PF_1))
else:
sl_profit = HSL

if sl_profit >= current_profit:


return -0.99

return stoploss_from_open(sl_profit, current_profit)

def populate_indicators(self, dataframe: DataFrame, metadata: dict) ->


DataFrame:

inf_tf = '5m'
informative = [Link].get_pair_dataframe('BTC/USDT:USDT', timeframe=inf_tf)
informative_btc = [Link]().shift(1)

dataframe['btc_close'] = informative_btc['close']
dataframe['btc_ema_fast'] = [Link](informative_btc, timeperiod=20)
dataframe['btc_ema_slow'] = [Link](informative_btc, timeperiod=25)
dataframe['down'] = (dataframe['btc_ema_fast'] <
dataframe['btc_ema_slow']).astype('int')
for val in self.base_nb_candles_sell.range:
dataframe[f'ma_sell_{val}'] = [Link](dataframe, timeperiod=val)

dataframe['volume_mean_12'] =
dataframe['volume'].rolling(12).mean().shift(1)
dataframe['volume_mean_24'] =
dataframe['volume'].rolling(24).mean().shift(1)

dataframe['cmf'] = chaikin_money_flow(dataframe, 20)

bollinger2 = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe),
window=20, stds=2)
dataframe['bb_lowerband2'] = bollinger2['lower']
dataframe['bb_middleband2'] = bollinger2['mid']
dataframe['bb_upperband2'] = bollinger2['upper']
dataframe['bb_width'] = ((dataframe['bb_upperband2'] -
dataframe['bb_lowerband2']) / dataframe['bb_middleband2'])

bollinger2_40 = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe),
window=40, stds=2)
dataframe['bb_lowerband2_40'] = bollinger2_40['lower']
dataframe['bb_middleband2_40'] = bollinger2_40['mid']
dataframe['bb_upperband2_40'] = bollinger2_40['upper']

dataframe['ema_200'] = [Link](dataframe, timeperiod=200)


dataframe['ema_50'] = [Link](dataframe, timeperiod=50)

dataframe['rsi'] = [Link](dataframe, timeperiod=14)


dataframe['rsi_fast'] = [Link](dataframe, timeperiod=4)
dataframe['rsi_slow'] = [Link](dataframe, timeperiod=20)
dataframe['rsi_84'] = [Link](dataframe, timeperiod=84)
dataframe['rsi_112'] = [Link](dataframe, timeperiod=112)

heikinashi = [Link](dataframe)
dataframe['ha_open'] = heikinashi['open']
dataframe['ha_close'] = heikinashi['close']
dataframe['ha_high'] = heikinashi['high']
dataframe['ha_low'] = heikinashi['low']

dataframe['bb_delta_cluc'] = (dataframe['bb_middleband2_40'] -
dataframe['bb_lowerband2_40']).abs()
dataframe['ha_closedelta'] = (dataframe['ha_close'] -
dataframe['ha_close'].shift()).abs()

stoch = [Link](dataframe, 15, 20, 2, 2)


dataframe['srsi_fk'] = stoch['fastk']
dataframe['srsi_fd'] = stoch['fastd']

mid, lower = bollinger_bands(ha_typical_price(dataframe), window_size=40,


num_of_std=2)
dataframe['lower'] = lower
dataframe['mid'] = mid

dataframe['bbdelta'] = (mid - dataframe['lower']).abs()


dataframe['closedelta'] = (dataframe['ha_close'] -
dataframe['ha_close'].shift()).abs()
dataframe['tail'] = (dataframe['ha_close'] - dataframe['ha_low']).abs()
dataframe['bb_lowerband'] = dataframe['lower']
dataframe['bb_middleband'] = dataframe['mid']

bollinger3 = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe),
window=20, stds=3)
dataframe['bb_lowerband3'] = bollinger3['lower']
dataframe['bb_middleband3'] = bollinger3['mid']
dataframe['bb_upperband3'] = bollinger3['upper']
dataframe['bb_delta'] = ((dataframe['bb_lowerband2'] -
dataframe['bb_lowerband3']) / dataframe['bb_lowerband2'])

dataframe['ema_fast'] = [Link](dataframe['ha_close'], timeperiod=3)


dataframe['ema_slow'] = [Link](dataframe['ha_close'], timeperiod=50)
dataframe['volume_mean_slow'] =
dataframe['volume'].rolling(window=30).mean()
dataframe['rocr'] = [Link](dataframe['ha_close'], timeperiod=28)

vwap_low, vwap, vwap_high = VWAPB(dataframe, 20, 1)

vwap_low, vwap, vwap_high = VWAPB(dataframe, 20, 1)


dataframe['vwap_low'] = vwap_low

dataframe['vwap_upperband'] = vwap_high
dataframe['vwap_middleband'] = vwap
dataframe['vwap_lowerband'] = vwap_low
dataframe['vwap_width'] = ( (dataframe['vwap_upperband'] -
dataframe['vwap_lowerband']) / dataframe['vwap_middleband'] ) * 100

dataframe['ema_vwap_diff_50'] = ( ( dataframe['ema_50'] -
dataframe['vwap_lowerband'] ) / dataframe['ema_50'] )

dataframe['tpct_change_0'] = top_percent_change_dca(dataframe,0)
dataframe['tpct_change_1'] = top_percent_change_dca(dataframe,1)
dataframe['tcp_percent_4'] = top_percent_change_dca(dataframe , 4)

dataframe['ewo'] = ewo(dataframe, 50, 200)

for val in self.buy_rmi_length.range:


dataframe[f'rmi_length_{val}'] = RMI(dataframe, length=val, mom=4)

for val in self.buy_cci_length.range:


dataframe[f'cci_length_{val}'] = [Link](dataframe, val)

dataframe['cti'] = [Link](dataframe["close"], length=20)

dataframe['bb_delta_cluc'] = (dataframe['bb_middleband2_40'] -
dataframe['bb_lowerband2_40']).abs()

dataframe['ema_16'] = [Link](dataframe, timeperiod=16)

dataframe['EWO'] = EWO(dataframe, self.fast_ewo, self.slow_ewo)

dataframe['ema_26'] = [Link](dataframe, timeperiod=26)


dataframe['ema_12'] = [Link](dataframe, timeperiod=12)

dataframe['r_14'] = williams_r(dataframe, period=14)


dataframe['ema_5'] = [Link](dataframe, timeperiod=5)
dataframe['ema_10'] = [Link](dataframe, timeperiod=10)

dataframe['pm'], dataframe['pmx'] = pmax(heikinashi, MAtype=1, length=9,


multiplier=27, period=10, src=3)
dataframe['source'] = (dataframe['high'] + dataframe['low'] +
dataframe['open'] + dataframe['close'])/4
dataframe['pmax_thresh'] = [Link](dataframe['source'], timeperiod=9)
dataframe['sma_75'] = [Link](dataframe, timeperiod=75)

rsi = [Link](dataframe)
dataframe["rsi"] = rsi
rsi = 0.1 * (rsi - 50)
dataframe["fisher"] = ([Link](2 * rsi) - 1) / ([Link](2 * rsi) + 1)

inf_tf = '1h'

informative = [Link].get_pair_dataframe(pair=metadata['pair'],
timeframe=inf_tf)

inf_heikinashi = [Link](informative)

informative['ha_close'] = inf_heikinashi['close']
informative['rocr'] = [Link](informative['ha_close'], timeperiod=168)
informative['rsi_14'] = [Link](dataframe, timeperiod=14)
informative['cmf'] = chaikin_money_flow(dataframe, 20)

sup_series = informative['low'].rolling(window = 5).apply(lambda row:


self.is_support(row), raw=True)
informative['sup_level'] = Series([Link](sup_series,
[Link](informative['close'] < informative['open'], informative['close'],
informative['open']), float('NaN'))).ffill()
informative['roc'] = [Link](informative, timeperiod=9)

informative['r_480'] = williams_r(informative, period=480)

bollinger2 = qtpylib.bollinger_bands(qtpylib.typical_price(informative),
window=20, stds=2)
informative['bb_lowerband2'] = bollinger2['lower']
informative['bb_middleband2'] = bollinger2['mid']
informative['bb_upperband2'] = bollinger2['upper']
informative['bb_width'] = ((informative['bb_upperband2'] -
informative['bb_lowerband2']) / informative['bb_middleband2'])

informative['r_84'] = williams_r(informative, period=84)


informative['cti_40'] = [Link](informative["close"], length=40)

dataframe['hma_50'] = qtpylib.hull_moving_average(dataframe['close'],
window=50)

dataframe = merge_informative_pair(dataframe, informative, [Link],


inf_tf, ffill=True)

return dataframe

def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) ->


DataFrame:
[Link][
((dataframe[f'rmi_length_{self.buy_rmi_length.value}'] <
self.buy_rmi.value) &
(dataframe[f'cci_length_{self.buy_cci_length.value}'] <=
self.buy_cci.value) &
(dataframe['srsi_fk'] < self.buy_srsi_fk.value) &
(dataframe['bb_delta'] > self.buy_bb_delta.value) &
(dataframe['bb_width'] > self.buy_bb_width.value) &
(dataframe['closedelta'] > dataframe['close'] *
self.buy_closedelta.value / 1000 ) & # from BinH
(dataframe['close'] < dataframe['bb_lowerband3'] *
self.buy_bb_factor.value)&
(dataframe['roc_1h'] < self.buy_roc_1h.value) &
(dataframe['bb_width_1h'] < self.buy_bb_width_1h.value)
),
['enter_long', 'enter_tag']] = (1, 'DIP signal')

[Link][

((dataframe['bb_delta'] > self.buy_bb_delta.value) &


(dataframe['bb_width'] > self.buy_bb_width.value) &
(dataframe['closedelta'] > dataframe['close'] *
self.buy_closedelta.value / 1000 ) & # from BinH
(dataframe['close'] < dataframe['bb_lowerband3'] *
self.buy_bb_factor.value)&
(dataframe['roc_1h'] < self.buy_roc_1h.value) &
(dataframe['bb_width_1h'] < self.buy_bb_width_1h.value)

),
['enter_long', 'enter_tag']] = (1, 'Break signal')

[Link][

((dataframe['rocr_1h'] > self.buy_clucha_rocr_1h.value ) &

(dataframe['bb_lowerband2_40'].shift() > 0) &


(dataframe['bb_delta_cluc'] > dataframe['ha_close'] *
self.buy_clucha_bbdelta_close.value) &
(dataframe['ha_closedelta'] > dataframe['ha_close'] *
self.buy_clucha_closedelta_close.value) &
(dataframe['tail'] < dataframe['bb_delta_cluc'] *
self.buy_clucha_bbdelta_tail.value) &
(dataframe['ha_close'] <
dataframe['bb_lowerband2_40'].shift()) &
(dataframe['close'] > (dataframe['sup_level_1h'] * 0.88)) &
(dataframe['ha_close'] < dataframe['ha_close'].shift())

),
['enter_long', 'enter_tag']] = (1, 'cluc_HA')

[Link][
((dataframe['ema_200'] > (dataframe['ema_200'].shift(12) * 1.01)) &
(dataframe['ema_200'] > (dataframe['ema_200'].shift(48) * 1.07)) &
(dataframe['bb_lowerband2_40'].shift().gt(0)) &
(dataframe['bb_delta_cluc'].gt(dataframe['close'] * 0.056)) &
(dataframe['closedelta'].gt(dataframe['close'] * 0.01)) &
(dataframe['tail'].lt(dataframe['bb_delta_cluc'] * 0.5)) &
(dataframe['close'].lt(dataframe['bb_lowerband2_40'].shift())) &
(dataframe['close'].le(dataframe['close'].shift())) &
(dataframe['close'] > dataframe['ema_50'] * 0.912)

),
['enter_long', 'enter_tag']] = (1, 'NFIX39')

[Link][
((dataframe['close'] > (dataframe['sup_level_1h'] * 0.72)) &
(dataframe['close'] < (dataframe['ema_16'] * 0.982)) &
(dataframe['EWO'] < -10.0) &
(dataframe['cti'] < -0.9)

),
['enter_long', 'enter_tag']] = (1, 'NFIX29')

[Link][
((dataframe['ema_26'] > dataframe['ema_12']) &
(dataframe['ema_26'] - dataframe['ema_12'] > dataframe['open'] *
self.buy_ema_diff.value) &
(dataframe['ema_26'].shift() - dataframe['ema_12'].shift() >
dataframe['open'] / 100) &
(dataframe['close'] < dataframe['bb_lowerband2'] *
self.buy_bb_factor.value) &
(dataframe['closedelta'] > dataframe['close'] *
self.buy_closedelta.value / 1000 )

),
['enter_long', 'enter_tag']] = (1, 'local_uptrend')

[Link][
(

(dataframe['close'] < dataframe['vwap_low']) &


(dataframe['tcp_percent_4'] > 0.053) & # 0.053)
(dataframe['cti'] < -0.8) & # -0.8)
(dataframe['rsi'] < 35) &
(dataframe['rsi_84'] < 60) &
(dataframe['rsi_112'] < 60) &

(dataframe['volume'] > 0)
),
['enter_long', 'enter_tag']] = (1, 'vwap')

[Link][
((dataframe['bb_width_1h'] > 0.131) &
(dataframe['r_14'] < -51) &
(dataframe['r_84_1h'] < -70) &
(dataframe['cti'] < -0.845) &
(dataframe['cti_40_1h'] < -0.735)
&
( (dataframe['close'].rolling(48).max() >= (dataframe['close'] *
1.1 )) ) &
(dataframe['btc_close'].rolling(24).max() >=
(dataframe['btc_close'] * 1.03 ))
),
['enter_long', 'enter_tag']] = (1, 'insta_signal')

[Link][
((dataframe['close'] < (dataframe['ema_16'] * self.buy_44_ma_offset))&
(dataframe['ewo'] < self.buy_44_ewo)&
(dataframe['cti'] < self.buy_44_cti)&
(dataframe['r_480_1h'] < self.buy_44_r_1h)&
(dataframe['volume'] > 0)
),
['enter_long', 'enter_tag']] = (1, 'NFINext44')

[Link][
((dataframe['pm'] > dataframe['pmax_thresh'])&
(dataframe['close'] < dataframe['sma_75'] * self.buy_37_ma_offset)&
(dataframe['ewo'] > self.buy_37_ewo)&
(dataframe['rsi'] < self.buy_37_rsi)&
(dataframe['cti'] < self.buy_37_cti)

),
['enter_long', 'enter_tag']] = (1, 'NFINext37')

[Link][
((dataframe['ema_26'] > dataframe['ema_12'])&
((dataframe['ema_26'] - dataframe['ema_12']) > (dataframe['open'] *
self.buy_ema_open_mult_7))&
((dataframe['ema_26'].shift() - dataframe['ema_12'].shift()) >
(dataframe['open'] / 100))&
(dataframe['cti'] < self.buy_cti_7)

),
['enter_long', 'enter_tag']] = (1, 'NFINext7')

return dataframe

def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) ->


DataFrame:

[Link][
(dataframe['fisher'] > self.sell_fisher.value) &
(dataframe['ha_high'].le(dataframe['ha_high'].shift(1))) &
(dataframe['ha_high'].shift(1).le(dataframe['ha_high'].shift(2))) &
(dataframe['ha_close'].le(dataframe['ha_close'].shift(1))) &
(dataframe['ema_fast'] > dataframe['ha_close']) &
((dataframe['ha_close'] * self.sell_bbmiddle_close.value) >
dataframe['bb_middleband']) &
(dataframe['volume'] > 0),
'exit_long'
] = 0

return dataframe
initial_safety_order_trigger = -0.018
max_safety_orders = 8
safety_order_step_scale = 1.2
safety_order_volume_scale = 1.4

def top_percent_change_dca(self, dataframe: DataFrame, length: int) -> float:


"""
Percentage change of the current close from the range maximum Open price

:param dataframe: DataFrame The original OHLC dataframe


:param length: int The length to look back
"""
if length == 0:
return (dataframe['open'] - dataframe['close']) / dataframe['close']
else:
return (dataframe['open'].rolling(length).max() - dataframe['close']) /
dataframe['close']

def adjust_trade_position(self, trade: Trade, current_time: datetime,


current_rate: float, current_profit: float,
min_stake: float,
max_stake: float, **kwargs):
if current_profit > self.initial_safety_order_trigger:
return None

dataframe, _ = [Link].get_analyzed_dataframe([Link], [Link])

last_candle = [Link][-1].squeeze()

filled_buys = trade.select_filled_orders('buy')
count_of_buys = len(filled_buys)
if count_of_buys == 1 and (last_candle['tpct_change_0'] > 0.018) and
(last_candle['close'] < last_candle['open']) :

return None
elif count_of_buys == 2 and (last_candle['tpct_change_0'] > 0.018) and
(last_candle['close'] < last_candle['open']) and (last_candle['ema_vwap_diff_50'] <
0.215):

return None
elif count_of_buys == 3 and (last_candle['tpct_change_0'] > 0.018) and
(last_candle['close'] < last_candle['open'])and (last_candle['ema_vwap_diff_50'] <
0.215) :
return None
elif count_of_buys == 4 and (last_candle['tpct_change_0'] > 0.018) and
(last_candle['close'] < last_candle['open'])and (last_candle['ema_vwap_diff_50'] <
0.215) and (last_candle['ema_5']) >= (last_candle['ema_10']):

return None
elif count_of_buys == 5 and (last_candle['cmf_1h'] < 0.00) and
(last_candle['close'] < last_candle['open']) and (last_candle['rsi_14_1h'] < 30)
and (last_candle['tpct_change_0'] > 0.018) and (last_candle['close'] <
last_candle['open']) and (last_candle['ema_vwap_diff_50'] < 0.215) and
(last_candle['ema_5']) >= (last_candle['ema_10']):

[Link](f"DCA for {[Link]} waiting for cmf_1h


({last_candle['cmf_1h']}) to rise above 0. Waiting for rsi_1h
({last_candle['rsi_14_1h']})to rise above 30")
return None
elif count_of_buys == 6 and (last_candle['cmf_1h'] < 0.00) and
(last_candle['close'] < last_candle['open']) and (last_candle['rsi_14_1h'] < 30)
and (last_candle['tpct_change_0'] > 0.018) and (last_candle['close'] <
last_candle['open'] and (last_candle['ema_vwap_diff_50'] < 0.215)) and
(last_candle['ema_5']) >= (last_candle['ema_10']):

[Link](f"DCA for {[Link]} waiting for cmf_1h


({last_candle['cmf_1h']}) to rise above 0. Waiting for rsi_1h
({last_candle['rsi_14_1h']})to rise above 30")
return None
elif count_of_buys == 7 and (last_candle['cmf_1h'] < 0.00) and
(last_candle['close'] < last_candle['open']) and (last_candle['rsi_14_1h'] < 30)
and (last_candle['tpct_change_0'] > 0.018) and (last_candle['close'] <
last_candle['open'] and (last_candle['ema_vwap_diff_50'] < 0.215)) and
(last_candle['ema_5']) >= (last_candle['ema_10']):

[Link](f"DCA for {[Link]} waiting for cmf_1h


({last_candle['cmf_1h']}) to rise above 0. Waiting for rsi_1h
({last_candle['rsi_14_1h']})to rise above 30")
return None
elif count_of_buys == 8 and (last_candle['cmf_1h'] < 0.00) and
(last_candle['close'] < last_candle['open']) and (last_candle['rsi_14_1h'] < 30)
and (last_candle['tpct_change_0'] > 0.018) and (last_candle['close'] <
last_candle['open'] and (last_candle['ema_vwap_diff_50'] < 0.215)) and
(last_candle['ema_5']) >= (last_candle['ema_10']):

[Link](f"DCA for {[Link]} waiting for cmf_1h


({last_candle['cmf_1h']}) to rise above 0. Waiting for rsi_1h
({last_candle['rsi_14_1h']})to rise above 30")
return None
if 1 <= count_of_buys <= self.max_safety_orders:
safety_order_trigger = (abs(self.initial_safety_order_trigger) *
count_of_buys)
if (self.safety_order_step_scale > 1):
safety_order_trigger = abs(self.initial_safety_order_trigger) +
(abs(self.initial_safety_order_trigger) * self.safety_order_step_scale *
([Link](self.safety_order_step_scale,(count_of_buys - 1)) - 1) /
(self.safety_order_step_scale - 1))
elif (self.safety_order_step_scale < 1):
safety_order_trigger = abs(self.initial_safety_order_trigger) +
(abs(self.initial_safety_order_trigger) * self.safety_order_step_scale * (1 -
[Link](self.safety_order_step_scale,(count_of_buys - 1))) / (1 -
self.safety_order_step_scale))

if current_profit <= (-1 * abs(safety_order_trigger)):


try:

stake_amount = filled_buys[0].cost

stake_amount = stake_amount *
[Link](self.safety_order_volume_scale,(count_of_buys - 1))
amount = stake_amount / current_rate
[Link](f"Initiating safety order buy #{count_of_buys} for
{[Link]} with stake amount of {stake_amount} which equals {amount}")
return stake_amount
except Exception as exception:
[Link](f'Error occured while trying to get stake amount
for {[Link]}: {str(exception)}')
return None

return None

def pmax(df, period, multiplier, length, MAtype, src):

period = int(period)
multiplier = int(multiplier)
length = int(length)
MAtype = int(MAtype)
src = int(src)

mavalue = 'MA_' + str(MAtype) + '_' + str(length)


atr = 'ATR_' + str(period)
pm = 'pm_' + str(period) + '_' + str(multiplier) + '_' + str(length) + '_' +
str(MAtype)
pmx = 'pmX_' + str(period) + '_' + str(multiplier) + '_' + str(length) + '_' +
str(MAtype)
if src == 1:
masrc = df["close"]
elif src == 2:
masrc = (df["high"] + df["low"]) / 2
elif src == 3:
masrc = (df["high"] + df["low"] + df["close"] + df["open"]) / 4

if MAtype == 1:
mavalue = [Link](masrc, timeperiod=length)
elif MAtype == 2:
mavalue = [Link](masrc, timeperiod=length)
elif MAtype == 3:
mavalue = ta.T3(masrc, timeperiod=length)
elif MAtype == 4:
mavalue = [Link](masrc, timeperiod=length)
elif MAtype == 5:
mavalue = VIDYA(df, length=length)
elif MAtype == 6:
mavalue = [Link](masrc, timeperiod=length)
elif MAtype == 7:
mavalue = [Link](df, timeperiod=length)
elif MAtype == 8:
mavalue = vwma(df, length)
elif MAtype == 9:
mavalue = zema(df, period=length)

df[atr] = [Link](df, timeperiod=period)


df['basic_ub'] = mavalue + ((multiplier/10) * df[atr])
df['basic_lb'] = mavalue - ((multiplier/10) * df[atr])

basic_ub = df['basic_ub'].values
final_ub = [Link](len(df), 0.00)
basic_lb = df['basic_lb'].values
final_lb = [Link](len(df), 0.00)

for i in range(period, len(df)):


final_ub[i] = basic_ub[i] if (
basic_ub[i] < final_ub[i - 1]
or mavalue[i - 1] > final_ub[i - 1]) else final_ub[i - 1]
final_lb[i] = basic_lb[i] if (
basic_lb[i] > final_lb[i - 1]
or mavalue[i - 1] < final_lb[i - 1]) else final_lb[i - 1]

df['final_ub'] = final_ub
df['final_lb'] = final_lb

pm_arr = [Link](len(df), 0.00)


for i in range(period, len(df)):
pm_arr[i] = (
final_ub[i] if (pm_arr[i - 1] == final_ub[i - 1]
and mavalue[i] <= final_ub[i])
else final_lb[i] if (
pm_arr[i - 1] == final_ub[i - 1]
and mavalue[i] > final_ub[i]) else final_lb[i]
if (pm_arr[i - 1] == final_lb[i - 1]
and mavalue[i] >= final_lb[i]) else final_ub[i]
if (pm_arr[i - 1] == final_lb[i - 1]
and mavalue[i] < final_lb[i]) else 0.00)
pm = Series(pm_arr)

pmx = [Link]((pm_arr > 0.00), [Link]((mavalue < pm_arr), 'down', 'up'),


[Link])

return pm, pmx

def run_backtest(symbol = SYMBOLS):


all_trades = []
data = fetch_all_data()
for symbol in SYMBOLS:
try:
if symbol not in data:
continue

# ‫جلب البيانات التاريخية للإطارات الزمنية الثالثة‬


df_1h = fetch_data(symbol, '1h')
df_15m = fetch_data(symbol, '15m')
df_4h = fetch_data(symbol, '4h')

# ‫حساب المؤشرات على الإطار الرئيسي‬


df_main = compute_indicators(df_1h.copy())

# ‫ على الإطارات الفرعية على الأقل حساب‬VWAP


df_15m['VWAP'] = ((df_15m['high'] + df_15m['low'] +
df_15m['close'])/3 * df_15m['volume']).cumsum() / df_15m['volume'].cumsum()
df_4h['VWAP'] = ((df_4h['high'] + df_4h['low'] + df_4h['close'])/3
* df_4h['volume']).cumsum() / df_4h['volume'].cumsum()

trades = []
position = None
entry_price = None
stop_loss = None
take_profit = None
trailing_stop = None
trade_entry_time = None
pos_size = 0
trades_df = [Link](trades)
trades_df['symbol'] = symbol
all_trades.append(trades_df)

# )‫ شمعة‬200 ‫نبدأ من لحظة تكون البيانات كافية (مثًال بعد‬


for i in range(200, len(df_main)):
current = df_main.iloc[i]
time_current = df_main.index[i]
# ‫ نبحث عن إشارة دخول‬،‫إذا لم تكن هناك صفقة مفتوحة‬
if position is None:
signal = check_entry_signal(df_main, df_15m, df_4h, i)
if signal == 'long':
position = 'long'
entry_price = current['open'] # ‫الدخول عند سعر الفتح‬
trade_entry_time = time_current
stop_loss = entry_price * (1 - SL_BUFFER_PERCENT)
take_profit = entry_price * (1 + TARGET_PROFIT_PERCENT)
trailing_stop = stop_loss
pos_size = calculate_position_size(entry_price,
stop_loss, CAPITAL, RISK_PER_TRADE)
trade = {
'entry_time': trade_entry_time,
'position': position,
'entry_price': entry_price,
'stop_loss': stop_loss,
'take_profit': take_profit,
'position_size': pos_size,
'exit_time': None,
'exit_price': None,
'result': None
}
[Link](f"{trade_entry_time} - LONG entry at
{entry_price:.2f}, SL: {stop_loss:.2f}, TP: {take_profit:.2f}, Size:
{pos_size:.4f}")
elif signal == 'short':
position = 'short'
entry_price = current['open']
trade_entry_time = time_current
stop_loss = entry_price * (1 + SL_BUFFER_PERCENT)
take_profit = entry_price * (1 - TARGET_PROFIT_PERCENT)
trailing_stop = stop_loss
pos_size = calculate_position_size(entry_price,
stop_loss, CAPITAL, RISK_PER_TRADE)
trade = {
'entry_time': trade_entry_time,
'position': position,
'entry_price': entry_price,
'stop_loss': stop_loss,
'take_profit': take_profit,
'position_size': pos_size,
'exit_time': None,
'exit_price': None,
'result': None
}
[Link](f"{trade_entry_time} - SHORT entry at
{entry_price:.2f}, SL: {stop_loss:.2f}, TP: {take_profit:.2f}, Size:
{pos_size:.4f}")
else:
continue
else:
# ‫ إدارة الصفقة المفتوحة مع‬Trailing Stop
if position == 'long':
# ‫ تحديث‬Trailing Stop: ‫ نحرك وقف‬،‫إذا ارتفع السعر‬
‫الخسارة تدريجيًا‬
if current['high'] > entry_price:
new_trailing = current['low'] * 1.001 # ‫مثال على‬
‫تحديث بسيط‬
if new_trailing > trailing_stop:
trailing_stop = new_trailing
# ‫ الخروج إذا وصل السعر إلى‬TP ‫ أو تراجع إلى‬Trailing
Stop
if current['low'] <= trailing_stop:
exit_price = trailing_stop
result = (exit_price - entry_price) * pos_size
[Link]({'exit_time': time_current,
'exit_price': exit_price, 'result': result})
[Link](trade)
[Link](f"{time_current} - LONG exit at
{exit_price:.2f}, Result: {result:.2f}")
position = None
elif current['high'] >= take_profit:
exit_price = take_profit
result = (exit_price - entry_price) * pos_size
[Link]({'exit_time': time_current,
'exit_price': exit_price, 'result': result})
[Link](trade)
[Link](f"{time_current} - LONG TP hit at
{exit_price:.2f}, Result: {result:.2f}")
position = None
elif position == 'short':
if current['low'] < entry_price:
new_trailing = current['high'] * 0.999 # ‫تحديث‬
Trailing Stop ‫للصفقة القصيرة‬
if new_trailing < trailing_stop:
trailing_stop = new_trailing
if current['high'] >= trailing_stop:
exit_price = trailing_stop
result = (entry_price - exit_price) * pos_size
[Link]({'exit_time': time_current,
'exit_price': exit_price, 'result': result})
[Link](trade)
[Link](f"{time_current} - SHORT exit at
{exit_price:.2f}, Result: {result:.2f}")
position = None
elif current['low'] <= take_profit:
exit_price = take_profit
result = (entry_price - exit_price) * pos_size
[Link]({'exit_time': time_current,
'exit_price': exit_price, 'result': result})
[Link](trade)
[Link](f"{time_current} - SHORT TP hit at
{exit_price:.2f}, Result: {result:.2f}")
position = None

trades_df = [Link](trades)

# ‫حساب مؤشرات الأداء‬:


# 1. ‫الخسارة‬/‫( نسبة الربح‬Profit-Loss Ratio)
winning_trades = trades_df[trades_df['result'] > 0]
losing_trades = trades_df[trades_df['result'] < 0]
avg_win = winning_trades['result'].mean() if not winning_trades.empty
else 0
avg_loss = abs(losing_trades['result'].mean()) if not
losing_trades.empty else 0
profit_loss_ratio = avg_win / avg_loss if avg_loss != 0 else [Link]
# 2. ‫( نسبة المخاطرة إلى العائد‬Risk-Reward Ratio) ‫على أساس الصفقات‬
‫الفردية‬
# ‫ لـ( نحسب المخاطرة لكل صفقة‬long: entry - SL، ‫ ولـ‬short: SL - entry)
trades_df['risk'] = [Link](trades_df['position'] == 'long',
trades_df['entry_price'] -
trades_df['stop_loss'],
trades_df['stop_loss'] -
trades_df['entry_price'])
# ‫نحسب نسبة العائد إلى المخاطرة لكل صفقة‬
trades_df['rr'] = [Link](trades_df['position'] == 'long',
(trades_df['exit_price'] -
trades_df['entry_price']) / trades_df['risk'],
(trades_df['entry_price'] -
trades_df['exit_price']) / trades_df['risk'])
avg_rr = trades_df['rr'].mean()

# 3. ‫ حساب الـ‬Drawdown
# ‫( نحسب مسار الحساب‬Equity Curve)
trades_df['equity'] = CAPITAL + trades_df['result'].cumsum()
trades_df['cummax'] = trades_df['equity'].cummax()
trades_df['drawdown'] = (trades_df['equity'] - trades_df['cummax']) /
trades_df['cummax']
max_drawdown = trades_df['drawdown'].min()

[Link](f"Total trades: {len(trades_df)}")


if not trades_df.empty:
[Link](f"Total PnL: {trades_df['result'].sum():.2f}")
[Link](f"Profit-Loss Ratio: {profit_loss_ratio:.2f}")
[Link](f"Average Risk-Reward Ratio: {avg_rr:.2f}")
[Link](f"Maximum Drawdown: {max_drawdown:.2%}")

return all_trades, [Link](all_trades) if all_trades else


[Link]()

stoploss: -0.99
timeframe: 5m
hash(sha256): 7be225086baa39441208d14dfe1faf86a86da7b89434339cf922167fa27dd439
indicators:
source bb_middleband2 ema_16 rsi_112 vwap_width
ema_vwap_diff_50 sma_75 low_offset fisher high_offset_2
ema_200 tcp_percent_4 cti ha_closedelta sup_level
cmf_1h ewo bb_upperband2 bb_lowerband base_nb_candles_buy
close bb_delta ema_26 high_offset rocr_1h
r_14 cm roc_1h bb_width_1h volume_mean_24
vwap roc bb_lowerband2_40 rsi_slow pm
r_480_1h lower r_84 basic_ub ema_12
cti_40 bb_middleband3 final_ub hma_50 btc_close
mid rsi_84 rsi_14 upper tpct_change_0
bb_upperband2_40 ema_10 btc_ema_slow pmx ma_stoploss: -0.99
timeframe: 5m
hash(sha256): 7be225086baa39441208d14dfe1faf86a86da7b89434339cf922167fa27dd439
indicators:
source bb_middleband2 ema_16 rsi_112 vwap_width
ema_vwap_diff_50 sma_75 low_offset fisher high_offset_2
ema_200 tcp_percent_4 cti ha_closedelta sup_level
cmf_1h ewo bb_upperband2 bb_lowerband base_nb_candles_buy
close bb_delta ema_26 high_offset rocr_1h
r_14 cm roc_1h bb_width_1h volume_mean_24
vwap roc bb_lowerband2_40 rsi_slow pm
r_480_1h lower r_84 basic_ub ema_12
cti_40 bb_middleband3 final_ub hma_50 btc_close
mid rsi_84 rsi_14 upper tpct_change_0
bb_upperband2_40 ema_10 btc_ema_slow pmx ma_

You might also like