Synchronise 2
This commit is contained in:
331
HeikinAshi.py
331
HeikinAshi.py
@@ -12,23 +12,62 @@
|
|||||||
# freqtrade hyperopt --hyperopt-loss SharpeHyperOptLoss --spaces roi buy --strategy Heracles
|
# freqtrade hyperopt --hyperopt-loss SharpeHyperOptLoss --spaces roi buy --strategy Heracles
|
||||||
# ######################################################################
|
# ######################################################################
|
||||||
# --- Do not remove these libs ---
|
# --- Do not remove these libs ---
|
||||||
from freqtrade.strategy.parameters import IntParameter, DecimalParameter
|
from freqtrade.persistence import Trade
|
||||||
from freqtrade.strategy.interface import IStrategy
|
from typing import Optional, Tuple, Union
|
||||||
|
from datetime import timezone, timedelta, datetime
|
||||||
|
from freqtrade.strategy import (BooleanParameter, CategoricalParameter, DecimalParameter, stoploss_from_open,
|
||||||
|
IntParameter, IStrategy, merge_informative_pair, informative, stoploss_from_absolute)
|
||||||
|
import logging
|
||||||
|
|
||||||
|
# noinspection PyUnresolvedReferences
|
||||||
|
from freqtrade.strategy import (IStrategy, informative)
|
||||||
from pandas import DataFrame
|
from pandas import DataFrame
|
||||||
# --------------------------------
|
# --------------------------------
|
||||||
# Add your lib to import here
|
# Add your lib to import here
|
||||||
# import talib.abstract as ta
|
# import talib.abstract as ta
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
import ta
|
import ta
|
||||||
|
import talib.abstract as talib
|
||||||
from ta.utils import dropna
|
from ta.utils import dropna
|
||||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
class Heracles(IStrategy):
|
class HeikinAshi(IStrategy):
|
||||||
########################################## RESULT PASTE PLACE ##########################################
|
plot_config = {
|
||||||
# 10/100: 25 trades. 18/4/3 Wins/Draws/Losses. Avg profit 5.92%. Median profit 6.33%. Total profit 0.04888306 BTC ( 48.88Σ%). Avg duration 4 days, 6:24:00 min. Objective: -11.42103
|
"main_plot": {
|
||||||
|
"min12": {
|
||||||
|
"color": "#197260"
|
||||||
|
},
|
||||||
|
'max12': {
|
||||||
|
'color': 'green'
|
||||||
|
},
|
||||||
|
"haclose": {
|
||||||
|
"color": "red"
|
||||||
|
},
|
||||||
|
'haopen': {
|
||||||
|
'color': 'blue'
|
||||||
|
},
|
||||||
|
"min288": {
|
||||||
|
"color": "#197260"
|
||||||
|
},
|
||||||
|
'max288': {
|
||||||
|
'color': 'green'
|
||||||
|
},
|
||||||
|
'mid288': {
|
||||||
|
'color': 'blue'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"subplots": {
|
||||||
|
"Percent": {
|
||||||
|
"hapercent": {
|
||||||
|
"color": "#74effc"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
# Buy hyperspace params:
|
# Buy hyperspace params:
|
||||||
buy_params = {
|
buy_params = {
|
||||||
@@ -44,53 +83,231 @@ class Heracles(IStrategy):
|
|||||||
|
|
||||||
# ROI table:
|
# ROI table:
|
||||||
minimal_roi = {
|
minimal_roi = {
|
||||||
"0": 0.598,
|
"0": 0.598
|
||||||
"644": 0.166,
|
|
||||||
"3269": 0.115,
|
|
||||||
"7289": 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Stoploss:
|
# Stoploss:
|
||||||
stoploss = -0.256
|
stoploss = -1
|
||||||
|
|
||||||
# Optimal timeframe use it in your config
|
# Optimal timeframe use it in your config
|
||||||
timeframe = '4h'
|
timeframe = '5m'
|
||||||
|
columns_logged = False
|
||||||
|
max_entry_position_adjustment = 20
|
||||||
|
startup_candle_count = 288
|
||||||
|
|
||||||
# Trailing stoploss
|
# Trailing stoploss
|
||||||
trailing_stop = True
|
# trailing_stop = False
|
||||||
trailing_stop_positive = 0.001
|
# trailing_stop_positive = 0.001
|
||||||
trailing_stop_positive_offset = 0.015
|
# trailing_stop_positive_offset = 0.015
|
||||||
trailing_only_offset_is_reached = True
|
# trailing_only_offset_is_reached = True
|
||||||
|
position_adjustment_enable = False
|
||||||
|
|
||||||
########################################## END RESULT PASTE PLACE ######################################
|
pairs = {
|
||||||
|
pair: {
|
||||||
|
"last_max": 0,
|
||||||
|
"trade_info": {},
|
||||||
|
"max_touch": 0.0,
|
||||||
|
"last_sell": 0.0,
|
||||||
|
"last_buy": 0.0
|
||||||
|
}
|
||||||
|
for pair in ["BTC/USDT", "ETH/USDT", "DOGE/USDT", "DASH/USDT", "XRP/USDT", "SOL/USDT"]
|
||||||
|
}
|
||||||
|
|
||||||
# buy params
|
decalage = IntParameter(0, 48, default=12, space='buy')
|
||||||
buy_div_min = DecimalParameter(0, 1, default=0.16, decimals=2, space='buy')
|
|
||||||
buy_div_max = DecimalParameter(0, 1, default=0.75, decimals=2, space='buy')
|
########################################## END RESULT PASTE PLACE #####################################
|
||||||
buy_indicator_shift = IntParameter(0, 20, default=16, space='buy')
|
# ------------------------------------------------------------------------------------------------------------------
|
||||||
buy_crossed_indicator_shift = IntParameter(0, 20, default=9, space='buy')
|
def adjust_trade_position(self, trade: Trade, current_time: datetime,
|
||||||
|
current_rate: float, current_profit: float,
|
||||||
|
min_stake: Optional[float], max_stake: float,
|
||||||
|
current_entry_rate: float, current_exit_rate: float,
|
||||||
|
current_entry_profit: float, current_exit_profit: float,
|
||||||
|
**kwargs
|
||||||
|
) -> Union[Optional[float], Tuple[Optional[float], Optional[str]]]:
|
||||||
|
|
||||||
|
|
||||||
|
# ne rien faire si ordre deja en cours
|
||||||
|
if trade.has_open_orders:
|
||||||
|
return None
|
||||||
|
|
||||||
|
dataframe, _ = self.dp.get_analyzed_dataframe(trade.pair, self.timeframe)
|
||||||
|
last_candle = dataframe.iloc[-1].squeeze()
|
||||||
|
last_candle_24 = dataframe.iloc[-25].squeeze()
|
||||||
|
# prépare les données
|
||||||
|
count_of_buys = trade.nr_of_successful_entries
|
||||||
|
current_time = current_time.astimezone(timezone.utc)
|
||||||
|
open_date = trade.open_date.astimezone(timezone.utc)
|
||||||
|
dispo = round(self.wallets.get_available_stake_amount())
|
||||||
|
|
||||||
|
limit_buy = 4
|
||||||
|
if (count_of_buys < limit_buy) \
|
||||||
|
and (last_candle['min288'] == last_candle_24['min288']) \
|
||||||
|
and (current_profit < -0.01 * count_of_buys) \
|
||||||
|
and (last_candle['close'] < last_candle['mid288']):
|
||||||
|
additional_stake = self.config['stake_amount']
|
||||||
|
self.log_trade(
|
||||||
|
last_candle=last_candle,
|
||||||
|
date=current_time,
|
||||||
|
action="Loss -",
|
||||||
|
dispo=dispo,
|
||||||
|
pair=trade.pair,
|
||||||
|
rate=current_rate,
|
||||||
|
trade_type='Decrease',
|
||||||
|
profit=round(current_profit, 4), # round(current_profit * trade.stake_amount, 2),
|
||||||
|
buys=trade.nr_of_successful_entries,
|
||||||
|
stake=round(additional_stake, 2)
|
||||||
|
)
|
||||||
|
return additional_stake
|
||||||
|
if (count_of_buys >= limit_buy) & (current_profit < - 0.03 * count_of_buys):
|
||||||
|
additional_stake = self.config['stake_amount'] * 2
|
||||||
|
self.log_trade(
|
||||||
|
last_candle=last_candle,
|
||||||
|
date=current_time,
|
||||||
|
action="Loss -",
|
||||||
|
dispo=dispo,
|
||||||
|
pair=trade.pair,
|
||||||
|
rate=current_rate,
|
||||||
|
trade_type='Decrease',
|
||||||
|
profit=round(current_profit, 4), # round(current_profit * trade.stake_amount, 2),
|
||||||
|
buys=trade.nr_of_successful_entries,
|
||||||
|
stake=round(additional_stake, 2)
|
||||||
|
)
|
||||||
|
return additional_stake
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def calculate_stake(self, pair, last_candle, factor=1):
|
||||||
|
amount = self.config['stake_amount'] * factor #1000 / self.first_stack_factor.value self.protection_stake_amount.value #
|
||||||
|
return amount
|
||||||
|
|
||||||
|
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], **kwargs) -> bool:
|
||||||
|
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
||||||
|
last_candle = dataframe.iloc[-1].squeeze()
|
||||||
|
dispo = round(self.wallets.get_available_stake_amount())
|
||||||
|
stake_amount = self.calculate_stake(pair, last_candle, 1)
|
||||||
|
|
||||||
|
self.log_trade(
|
||||||
|
last_candle=last_candle,
|
||||||
|
date=current_time,
|
||||||
|
action="START BUY",
|
||||||
|
pair=pair,
|
||||||
|
rate=rate,
|
||||||
|
dispo=dispo,
|
||||||
|
profit=0,
|
||||||
|
stake=round(stake_amount, 2)
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
|
||||||
|
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, **kwargs) -> bool:
|
||||||
|
|
||||||
|
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
||||||
|
last_candle = dataframe.iloc[-1].squeeze()
|
||||||
|
dispo = round(self.wallets.get_available_stake_amount())
|
||||||
|
|
||||||
|
allow_to_sell = (last_candle['percent5'] < -0.00)
|
||||||
|
ok = (allow_to_sell) | (exit_reason == 'force_exit')
|
||||||
|
if ok:
|
||||||
|
# self.pairs[pair]['last_max'] = 0
|
||||||
|
# self.pairs[pair]['max_touch'] = 0
|
||||||
|
self.pairs[pair]['last_buy'] = 0
|
||||||
|
self.pairs[pair]['last_sell'] = rate
|
||||||
|
self.log_trade(
|
||||||
|
last_candle=last_candle,
|
||||||
|
date=current_time,
|
||||||
|
action="Sell",
|
||||||
|
pair=pair,
|
||||||
|
trade_type=exit_reason,
|
||||||
|
rate=last_candle['close'],
|
||||||
|
dispo=dispo,
|
||||||
|
profit=round(trade.calc_profit(rate, amount), 2)
|
||||||
|
)
|
||||||
|
#print(f"Sell {current_time} {exit_reason} rate={rate:.3f} amount={amount} profit={amount * rate:.3f}")
|
||||||
|
|
||||||
|
return ok
|
||||||
|
|
||||||
|
def custom_exit(self, pair: str, trade: Trade, current_time, current_rate, current_profit, **kwargs):
|
||||||
|
|
||||||
|
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
||||||
|
last_candle = dataframe.iloc[-1].squeeze()
|
||||||
|
|
||||||
|
if (current_profit > 0.004) \
|
||||||
|
& (last_candle['hapercent'] < 0.0) \
|
||||||
|
& (last_candle['percent'] < 0.0):
|
||||||
|
count_of_buys = trade.nr_of_successful_entries
|
||||||
|
return 'profit_' + str(count_of_buys)
|
||||||
|
|
||||||
|
def log_trade(self, action, pair, date, trade_type=None, rate=None, dispo=None, profit=None, buys=None, stake=None, last_candle=None):
|
||||||
|
# Afficher les colonnes une seule fois
|
||||||
|
if self.config.get('runmode') == 'hyperopt':
|
||||||
|
return
|
||||||
|
if self.columns_logged % 30 == 0:
|
||||||
|
print(
|
||||||
|
f"| {'Date':<16} | {'Action':<10} | {'Pair':<10} | {'Trade Type':<18} | {'Rate':>12} | {'Dispo':>6} | {'Profit':>8} | {'Pct':>5} | {'max7_1d':>11} | {'max_touch':>12} | {'last_max':>12} | {'Buys':>5} | {'Stake':>10} |"
|
||||||
|
)
|
||||||
|
print(
|
||||||
|
f"|{'-' * 18}|{'-' * 12}|{'-' * 12}|{'-' * 20}|{'-' * 14}|{'-' * 8}|{'-' * 10}|{'-' * 7}|{'-' * 13}|{'-' * 14}|{'-' * 14}|{'-' * 7}|{'-' * 12}|"
|
||||||
|
)
|
||||||
|
self.columns_logged += 1
|
||||||
|
date = str(date)[:16] if date else "-"
|
||||||
|
limit = None
|
||||||
|
# if buys is not None:
|
||||||
|
# limit = round(last_rate * (1 - self.fibo[buys] / 100), 4)
|
||||||
|
|
||||||
|
rsi = ''
|
||||||
|
rsi_pct = ''
|
||||||
|
# if last_candle is not None:
|
||||||
|
# if (not np.isnan(last_candle['rsi_1d'])) and (not np.isnan(last_candle['rsi_1h'])):
|
||||||
|
# rsi = str(int(last_candle['rsi_1d'])) + " " + str(int(last_candle['rsi_1h']))
|
||||||
|
# if (not np.isnan(last_candle['rsi_pct_1d'])) and (not np.isnan(last_candle['rsi_pct_1h'])):
|
||||||
|
# rsi_pct = str(int(10000 * last_candle['bb_mid_pct_1d'])) + " " + str(
|
||||||
|
# int(last_candle['rsi_pct_1d'])) + " " + str(int(last_candle['rsi_pct_1h']))
|
||||||
|
|
||||||
|
# first_rate = self.percent_threshold.value
|
||||||
|
# last_rate = self.threshold.value
|
||||||
|
# action = self.color_line(action, action)
|
||||||
|
sma5_1d = ''
|
||||||
|
sma5_1h = ''
|
||||||
|
# if last_candle['sma5_pct_1d'] is not None:
|
||||||
|
# sma5_1d = round(last_candle['sma5_pct_1d'] * 100, 2)
|
||||||
|
# if last_candle['sma5_pct_1h'] is not None:
|
||||||
|
# sma5_1h = round(last_candle['sma5_pct_1h'] * 100, 2)
|
||||||
|
sma5 = str(sma5_1d) + ' ' + str(sma5_1h)
|
||||||
|
first_rate = self.pairs[pair]['last_max']
|
||||||
|
|
||||||
|
# if action != 'Sell':
|
||||||
|
# profit = round((last_candle['close'] - self.pairs[pair]['last_max']) / self.pairs[pair]['last_max'], 2)
|
||||||
|
|
||||||
|
limit_sell = rsi_pct # round((last_candle['close'] - self.pairs[pair]['last_max']) / self.pairs[pair]['last_max'], 4)
|
||||||
|
max7_1d = round(self.pairs[pair]['max_touch'], 1) #last_candle['max7_1d'] #round(100 * (last_candle['close'] - self.pairs[pair]['last_max']) / self.pairs[pair]['last_max'], 1)
|
||||||
|
pct_max = round(100 * (last_candle['close'] - max7_1d) / max7_1d, 1)
|
||||||
|
print(
|
||||||
|
f"| {date:<16} | {action:<10} | {pair:<10} | {trade_type or '-':<18} | {rate or '-':>12} | {dispo or '-':>6} | {profit or '-':>8} | {pct_max or '-':>5} | {max7_1d or '-':>11} | {round(self.pairs[pair]['max_touch'], 2) or '-':>12} | {round(self.pairs[pair]['last_max'],2) or '-':>12} | {buys or '-':>5} | {stake or '-':>10} |"
|
||||||
|
)
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||||
dataframe = dropna(dataframe)
|
heikinashi = qtpylib.heikinashi(dataframe)
|
||||||
|
dataframe['haopen'] = heikinashi['open']
|
||||||
|
dataframe['haclose'] = heikinashi['close']
|
||||||
|
dataframe['halow'] = heikinashi['low']
|
||||||
|
dataframe['hapercent'] = (dataframe['haclose'] - dataframe['haopen']) / dataframe['haclose']
|
||||||
|
dataframe['min12'] = talib.MIN(dataframe['close'], timeperiod=12)
|
||||||
|
dataframe['max12'] = talib.MAX(dataframe['close'], timeperiod=12)
|
||||||
|
dataframe['min288'] = talib.MIN(dataframe['close'], timeperiod=288)
|
||||||
|
dataframe['max288'] = talib.MAX(dataframe['close'], timeperiod=288)
|
||||||
|
dataframe['mid288'] = dataframe['min288'] + (dataframe['max288'] - dataframe['min288']) / 2
|
||||||
|
|
||||||
dataframe['volatility_kcw'] = ta.volatility.keltner_channel_wband(
|
dataframe["percent"] = (dataframe["close"] - dataframe["open"]) / dataframe["open"]
|
||||||
dataframe['high'],
|
dataframe["percent5"] = dataframe['close'].pct_change(5)
|
||||||
dataframe['low'],
|
|
||||||
dataframe['close'],
|
|
||||||
window=20,
|
|
||||||
window_atr=10,
|
|
||||||
fillna=False,
|
|
||||||
original_version=True
|
|
||||||
)
|
|
||||||
|
|
||||||
dataframe['volatility_dcp'] = ta.volatility.donchian_channel_pband(
|
# Bollinger Bands
|
||||||
dataframe['high'],
|
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
|
||||||
dataframe['low'],
|
dataframe['bb_lowerband'] = bollinger['lower']
|
||||||
dataframe['close'],
|
dataframe['bb_middleband'] = bollinger['mid']
|
||||||
window=10,
|
dataframe['bb_upperband'] = bollinger['upper']
|
||||||
offset=0,
|
dataframe['bb_diff'] = (dataframe['bb_upperband'] - dataframe['bb_lowerband']) / dataframe['bb_lowerband']
|
||||||
fillna=False
|
|
||||||
)
|
|
||||||
|
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
@@ -98,24 +315,20 @@ class Heracles(IStrategy):
|
|||||||
"""
|
"""
|
||||||
Buy strategy Hyperopt will build and use.
|
Buy strategy Hyperopt will build and use.
|
||||||
"""
|
"""
|
||||||
conditions = []
|
# dataframe.loc[
|
||||||
|
# (dataframe['halow'] <= dataframe['min12'])
|
||||||
IND = 'volatility_dcp'
|
# # & (dataframe['open'] <= dataframe['bb_middleband'])
|
||||||
CRS = 'volatility_kcw'
|
# # & (dataframe['bb_diff'] > 0.01)
|
||||||
DFIND = dataframe[IND]
|
# ,
|
||||||
DFCRS = dataframe[CRS]
|
# 'buy']=1
|
||||||
|
decalage = 3
|
||||||
d = DFIND.shift(self.buy_indicator_shift.value).div(
|
dataframe.loc[
|
||||||
DFCRS.shift(self.buy_crossed_indicator_shift.value))
|
(dataframe['halow'].shift(decalage) <= dataframe['min288'].shift(decalage))
|
||||||
|
& (dataframe['min288'].shift(decalage) == dataframe['min288'])
|
||||||
# print(d.min(), "\t", d.max())
|
# & (dataframe['open'] <= dataframe['bb_middleband'])
|
||||||
conditions.append(
|
# & (dataframe['bb_diff'] > 0.01)
|
||||||
d.between(self.buy_div_min.value, self.buy_div_max.value))
|
,
|
||||||
|
'buy']=1
|
||||||
if conditions:
|
|
||||||
dataframe.loc[
|
|
||||||
reduce(lambda x, y: x & y, conditions),
|
|
||||||
'buy']=1
|
|
||||||
|
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
@@ -123,5 +336,7 @@ class Heracles(IStrategy):
|
|||||||
"""
|
"""
|
||||||
Sell strategy Hyperopt will build and use.
|
Sell strategy Hyperopt will build and use.
|
||||||
"""
|
"""
|
||||||
dataframe.loc[:, 'sell'] = 0
|
# dataframe.loc[
|
||||||
|
# (qtpylib.crossed_above(dataframe['haclose'], dataframe['haopen'])),
|
||||||
|
# 'sell']=1
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|||||||
@@ -357,9 +357,6 @@ class Zeus_8_3_2_B_4_2(IStrategy):
|
|||||||
# print("---------------" + pair + "----------------")
|
# print("---------------" + pair + "----------------")
|
||||||
expected_profit = self.expectedProfit(pair, last_candle)
|
expected_profit = self.expectedProfit(pair, last_candle)
|
||||||
|
|
||||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
|
||||||
last_candle = dataframe.iloc[-1]
|
|
||||||
|
|
||||||
# Calcul du prix cible basé sur l'ATR
|
# Calcul du prix cible basé sur l'ATR
|
||||||
atr_take_profit = trade.open_rate + (last_candle['atr'] * 2) # Prendre profit à 2x l'ATR
|
atr_take_profit = trade.open_rate + (last_candle['atr'] * 2) # Prendre profit à 2x l'ATR
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user