/
HPStrategyLeverage.py
193 lines (154 loc) · 7.74 KB
/
HPStrategyLeverage.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
import logging
from typing import Optional
import pandas as pd
from technical import candles
from technical.candles import doji
from freqtrade.strategy.interface import IStrategy
from functools import reduce
from datetime import timedelta, datetime
from pandas import DataFrame, errors
# --------------------------------
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib
from freqtrade.persistence import Trade
from freqtrade.strategy import DecimalParameter, IntParameter, informative
import talib.abstract as ta
from warnings import simplefilter
simplefilter(action="ignore", category=errors.PerformanceWarning)
class HPStrategyLeverage(IStrategy):
INTERFACE_VERSION = 3
leverage_value = 3
# ROI table:
minimal_roi = {
"0": 0.215 * leverage_value,
"40": 0.032 * leverage_value,
"87": 0.016 * leverage_value,
"201": 0 * leverage_value
}
# Stoploss:
stoploss = -0.3 * leverage_value
# Trailing stop:
trailing_stop = True
trailing_stop_positive = 0.01 * leverage_value
trailing_stop_positive_offset = 0.02 * leverage_value
trailing_only_offset_is_reached = True
# Sell signal
use_exit_signal = True
exit_profit_only = True
exit_profit_offset = 0.01 * leverage_value
ignore_roi_if_entry_signal = False
# Optional order time in force.
order_time_in_force = {
'entry': 'gtc',
'exit': 'ioc'
}
# Optimal timeframe for the strategy
timeframe = '15m'
process_only_new_candles = True
startup_candle_count = 400
# plot_config = {
# 'main_plot': {
# 'ma_buy': {'color': 'orange'},
# 'ma_sell': {'color': 'orange'},
# },
# }
rolling_ha_treshold = IntParameter(1, 10, default=7, space='buy', optimize=True)
rsi_upper_limit = IntParameter(30, 70, default=50, space='buy', optimize=True)
rsi_buy_limit = IntParameter(5, 60, default=15, space='buy', optimize=True)
rsi_sell_limit = IntParameter(60, 95, default=75, space='sell', optimize=True)
roc_threshold = IntParameter(1, 10, default=2, space='buy', optimize=True)
doji_lastx = IntParameter(1, 10, default=10, space='buy', optimize=True)
doji_diff_threshold = DecimalParameter(0.003, 0.05, default=0.01, space='buy', optimize=True)
@informative('15m')
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# RSI
dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)
dataframe['rsi_fast'] = ta.RSI(dataframe, timeperiod=4)
dataframe['rsi_slow'] = ta.RSI(dataframe, timeperiod=20)
dataframe['roc'] = ((dataframe['close'] / dataframe['close'].shift(self.roc_threshold.value)) - 1) * 100
# Detekce doji svíček
dataframe['doji'] = (dataframe["open"] - dataframe["close"]).abs() <= (
(dataframe["high"] - dataframe["close"]) * self.doji_diff_threshold.value).abs().astype("float32")
dataframe['doji_last_x'] = dataframe['doji'].rolling(window=self.doji_lastx.value).sum() > 0
dataframe['ema_50'] = ta.EMA(dataframe, timeperiod=50)
return dataframe
def calculate_heiken_ashi(self, dataframe):
if dataframe.empty:
raise ValueError("DataFrame je prázdný")
heiken_ashi = pd.DataFrame(index=dataframe.index)
heiken_ashi['HA_Close'] = (dataframe['open'] + dataframe['high'] + dataframe['low'] + dataframe['close']) / 4
heiken_ashi['HA_Open'] = heiken_ashi['HA_Close'].shift(1)
heiken_ashi['HA_Open'].iloc[0] = heiken_ashi['HA_Close'].iloc[0]
heiken_ashi['HA_High'] = heiken_ashi[['HA_Open', 'HA_Close']].join(dataframe['high'], how='inner').max(axis=1)
heiken_ashi['HA_Low'] = heiken_ashi[['HA_Open', 'HA_Close']].join(dataframe['low'], how='inner').min(axis=1)
# Aplikace klouzavého průměru
heiken_ashi['HA_Close'] = heiken_ashi['HA_Close'].rolling(window=self.rolling_ha_treshold.value).mean()
heiken_ashi['HA_Open'] = heiken_ashi['HA_Open'].rolling(window=self.rolling_ha_treshold.value).mean()
heiken_ashi['HA_High'] = heiken_ashi['HA_High'].rolling(window=self.rolling_ha_treshold.value).mean()
heiken_ashi['HA_Low'] = heiken_ashi['HA_Low'].rolling(window=self.rolling_ha_treshold.value).mean()
return heiken_ashi
def should_buy(self, dataframe):
heiken_ashi = self.calculate_heiken_ashi(dataframe)
last_candle = heiken_ashi.iloc[-1]
if last_candle['HA_Close'] > last_candle['HA_Open']:
# Green Heiken-Ashi Candle - Bullish
return True
else:
# Red Heiken-Ashi Candle - Bearish
return False
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = []
# Kontrola doji svíčky pouze pokud je v uptrendu
uptrend = dataframe['close'] > dataframe['ema_50']
doji_in_uptrend = uptrend & (dataframe['doji_last_x'] > 0)
# Podmínka pro RSI a momentum
rsi_cond = (
(dataframe['rsi'] < self.rsi_buy_limit.value) & self.should_buy(dataframe)
)
conditions.append(rsi_cond)
momentum_cond = (
(dataframe['rsi_fast_15m'] < self.rsi_upper_limit.value) &
(dataframe['roc'] > self.roc_threshold.value) &
(dataframe['volume_15m'] > 0)
)
conditions.append(momentum_cond)
# Kombinace všech podmínek v seznamu do jedné Series pomocí reduce a operátoru &
combined_conditions = reduce(lambda x, y: x | y, conditions)
# Pak kombinujeme výsledek s no_doji_cond pomocí operátoru &
final_conditions = (combined_conditions & ~doji_in_uptrend)
# Aplikujeme finální podmínky na dataframe
dataframe.loc[final_conditions, ['enter_long', 'enter_tag']] = (1, 'rsi_momentum_ha_enter_long')
# Vyloučení předchozích nákupních signálů
dont_buy_conditions = [
(dataframe['enter_long'].shift(1) == 1)
]
if dont_buy_conditions:
for condition in dont_buy_conditions:
dataframe.loc[condition, 'enter_long'] = 0
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[(dataframe['rsi'] >= self.rsi_sell_limit.value), 'exit_long'] = 1
dont_exit_conditions = [
]
if dont_exit_conditions:
for condition in dont_exit_conditions:
dataframe.loc[condition, 'exit_long'] = 0
return dataframe
def confirm_trade_exit(self, pair: str, trade: Trade, order_type: str, amount: float,
rate: float, time_in_force: str, exit_reason: str,
current_time: datetime, **kwargs) -> bool:
default_reasons = ['force_sell', 'force_exit', 'roi', 'stop_loss', 'sell_signal', 'sell_profit_only',
'sell_profit_offset', 'sell_custom', 'sell_signal', 'trailing_stop_loss']
if (exit_reason in default_reasons):
logging.info(f"CTEN {pair} - {order_type} - {amount} - {rate} - {time_in_force}")
return True
return False
def confirm_trade_entry(self, pair: str, order_type: str, amount: float, rate: float,
time_in_force: str, current_time: datetime, entry_tag: Optional[str],
side: str, **kwargs) -> bool:
logging.info(f"CTEN {pair} - {order_type} - {amount} - {rate} - {time_in_force} - {side}")
return True
def leverage(self, pair: str, current_time: datetime, current_rate: float,
proposed_leverage: float, max_leverage: float, entry_tag: Optional[str], side: str,
**kwargs) -> float:
return self.leverage_value