first commit

This commit is contained in:
Jérôme Delacotte
2025-03-06 11:01:43 +01:00
commit 7c239227d8
558 changed files with 108235 additions and 0 deletions

962
GodStraJD3_7_5_10.py Normal file
View File

@@ -0,0 +1,962 @@
# GodStraNew Strategy
# Author: @Mablue (Masoud Azizi)
# github: https://github.com/mablue/
# freqtrade hyperopt --hyperopt-loss SharpeHyperOptLoss --spaces buy roi trailing sell --strategy GodStraNew
# --- Do not remove these libs ---
from datetime import timedelta, datetime
from typing import Optional
from freqtrade import data
from freqtrade.persistence import Trade
from freqtrade.strategy.parameters import CategoricalParameter, DecimalParameter, IntParameter, BooleanParameter
from numpy.lib import math
from freqtrade.strategy.interface import IStrategy
import pandas
from pandas import DataFrame
import time
import logging
import calendar
from freqtrade.loggers import setup_logging
from freqtrade.strategy.strategy_helper import merge_informative_pair
# --------------------------------
# Add your lib to import here
# TODO: talib is fast but have not more indicators
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib
from functools import reduce
import numpy as np
from random import shuffle
logger = logging.getLogger(__name__)
operators = [
"D", # Disabled gene
">", # Indicator, bigger than cross indicator
"<", # Indicator, smaller than cross indicator
"=", # Indicator, equal with cross indicator
"C", # Indicator, crossed the cross indicator
"CA", # Indicator, crossed above the cross indicator
"CB", # Indicator, crossed below the cross indicator
">R", # Normalized indicator, bigger than real number
"=R", # Normalized indicator, equal with real number
"<R", # Normalized indicator, smaller than real number
"/>R", # Normalized indicator devided to cross indicator, bigger than real number
"/=R", # Normalized indicator devided to cross indicator, equal with real number
"/<R", # Normalized indicator devided to cross indicator, smaller than real number
"UT", # Indicator, is in UpTrend status
"DT", # Indicator, is in DownTrend status
"OT", # Indicator, is in Off trend status(RANGE)
"CUT", # Indicator, Entered to UpTrend status
"CDT", # Indicator, Entered to DownTrend status
"COT" # Indicator, Entered to Off trend status(RANGE)
]
# number of candles to check up,don,off trend.
TREND_CHECK_CANDLES = 8
DECIMALS = 2
buy_crossed_indicator0 = 'MINUS_DM-5'
buy_operator0 = "/<R"
buy_indicator0 = 'MA-20'
buy_crossed_indicator1 = 'DX-5'
buy_operator1 = ">"
buy_indicator1 = 'STOCH-1-10'
buy_crossed_indicator2 = 'LINEARREG-50'
buy_operator2 = "/<R"
buy_indicator2 = 'CDLDRAGONFLYDOJI-5'
def normalize(df):
df = (df-df.min())/(df.max()-df.min())
return df
def gene_calculator(dataframe, indicator):
# Cuz Timeperiods not effect calculating CDL patterns recognations
if 'CDL' in indicator:
splited_indicator = indicator.split('-')
splited_indicator[1] = "0"
new_indicator = "-".join(splited_indicator)
# print(indicator, new_indicator)
indicator = new_indicator
gene = indicator.split("-")
gene_name = gene[0]
gene_len = len(gene)
if indicator in dataframe.keys():
# print(f"{indicator}, calculated befoure")
# print(len(dataframe.keys()))
return dataframe[indicator]
else:
result = None
# For Pattern Recognations
if gene_len == 1:
# print('gene_len == 1\t', indicator)
result = getattr(ta, gene_name)(
dataframe
)
return normalize(result)
elif gene_len == 2:
# print('gene_len == 2\t', indicator)
gene_timeperiod = int(gene[1])
result = getattr(ta, gene_name)(
dataframe,
timeperiod=gene_timeperiod,
)
return normalize(result)
# For
elif gene_len == 3:
# print('gene_len == 3\t', indicator)
gene_timeperiod = int(gene[2])
gene_index = int(gene[1])
result = getattr(ta, gene_name)(
dataframe,
timeperiod=gene_timeperiod,
).iloc[:, gene_index]
return normalize(result)
# For trend operators(MA-5-SMA-4)
elif gene_len == 4:
# print('gene_len == 4\t', indicator)
gene_timeperiod = int(gene[1])
sharp_indicator = f'{gene_name}-{gene_timeperiod}'
dataframe[sharp_indicator] = getattr(ta, gene_name)(
dataframe,
timeperiod=gene_timeperiod,
)
return normalize(ta.SMA(dataframe[sharp_indicator].fillna(0), TREND_CHECK_CANDLES))
# For trend operators(STOCH-0-4-SMA-4)
elif gene_len == 5:
# print('gene_len == 5\t', indicator)
gene_timeperiod = int(gene[2])
gene_index = int(gene[1])
sharp_indicator = f'{gene_name}-{gene_index}-{gene_timeperiod}'
dataframe[sharp_indicator] = getattr(ta, gene_name)(
dataframe,
timeperiod=gene_timeperiod,
).iloc[:, gene_index]
return normalize(ta.SMA(dataframe[sharp_indicator].fillna(0), TREND_CHECK_CANDLES))
def condition_generator(dataframe, operator, indicator, crossed_indicator, real_num, decalage):
condition = (dataframe['volume'] > 10)
# TODO : it ill callculated in populate indicators.
dataframe[indicator] = gene_calculator(dataframe, indicator)
dataframe[crossed_indicator] = gene_calculator(dataframe, crossed_indicator)
indicator_trend_sma = f"{indicator}-SMA-{TREND_CHECK_CANDLES}"
if operator in ["UT", "DT", "OT", "CUT", "CDT", "COT"]:
dataframe[indicator_trend_sma] = gene_calculator(dataframe, indicator_trend_sma)
if operator == ">":
condition = (dataframe[indicator].shift(decalage) > dataframe[crossed_indicator].shift(decalage))
elif operator == "=":
condition = (np.isclose(dataframe[indicator].shift(decalage), dataframe[crossed_indicator].shift(decalage)))
elif operator == "<":
condition = (dataframe[indicator].shift(decalage) < dataframe[crossed_indicator].shift(decalage))
elif operator == "C":
condition = (
(qtpylib.crossed_below(dataframe[indicator].shift(decalage), dataframe[crossed_indicator].shift(decalage))) |
(qtpylib.crossed_above(dataframe[indicator].shift(decalage), dataframe[crossed_indicator].shift(decalage)))
)
elif operator == "CA":
condition = (qtpylib.crossed_above(dataframe[indicator].shift(decalage), dataframe[crossed_indicator].shift(decalage)))
elif operator == "CB":
condition = (qtpylib.crossed_below(dataframe[indicator].shift(decalage), dataframe[crossed_indicator].shift(decalage)))
elif operator == ">R":
condition = (dataframe[indicator].shift(decalage) > real_num)
elif operator == "=R":
condition = (np.isclose(dataframe[indicator].shift(decalage), real_num))
elif operator == "<R":
condition = (dataframe[indicator].shift(decalage) < real_num)
elif operator == "/>R":
condition = (dataframe[indicator].shift(decalage).div(dataframe[crossed_indicator].shift(decalage)) > real_num)
elif operator == "/=R":
condition = (np.isclose(dataframe[indicator].shift(decalage).div(dataframe[crossed_indicator].shift(decalage)), real_num))
elif operator == "/<R":
condition = (dataframe[indicator].shift(decalage).div(dataframe[crossed_indicator].shift(decalage)) < real_num)
elif operator == "UT":
condition = (dataframe[indicator].shift(decalage) > dataframe[indicator_trend_sma].shift(decalage))
elif operator == "DT":
condition = (dataframe[indicator].shift(decalage) < dataframe[indicator_trend_sma].shift(decalage))
elif operator == "OT":
condition = (np.isclose(dataframe[indicator].shift(decalage), dataframe[indicator_trend_sma].shift(decalage)))
elif operator == "CUT":
condition = (
(
qtpylib.crossed_above(dataframe[indicator].shift(decalage), dataframe[indicator_trend_sma].shift(decalage))
) &
(
dataframe[indicator].shift(decalage) > dataframe[indicator_trend_sma].shift(decalage)
)
)
elif operator == "CDT":
condition = (
(
qtpylib.crossed_below(dataframe[indicator].shift(decalage), dataframe[indicator_trend_sma].shift(decalage))
) &
(
dataframe[indicator].shift(decalage) < dataframe[indicator_trend_sma].shift(decalage)
)
)
elif operator == "COT":
condition = (
(
(
qtpylib.crossed_below(dataframe[indicator].shift(decalage), dataframe[indicator_trend_sma].shift(decalage))
) |
(
qtpylib.crossed_above(dataframe[indicator].shift(decalage), dataframe[indicator_trend_sma].shift(decalage))
)
) &
(
np.isclose(dataframe[indicator].shift(decalage), dataframe[indicator_trend_sma].shift(decalage))
)
)
return condition, dataframe
class GodStraJD3_7_5_10(IStrategy):
# #################### RESULTS PASTE PLACE ####################
# ROI table:
minimal_roi = {
"0": 10,
# "600": 0.12,
# "1200": 0.08,
# "2400": 0.06,
# "3600": 0.04,
# "7289": 0
}
# Stoploss:
stoploss = -1
# Buy hypers
timeframe = '5m'
# Trailing stoploss
trailing_stop = False
trailing_stop_positive = 0.15
trailing_stop_positive_offset = 0.20
trailing_only_offset_is_reached = True
plot_config = {
# Main plot indicators (Moving averages, ...)
'main_plot': {
'bb_lowerband': {'color': 'red'},
'bb_upperband': {'color': 'green'},
'sma100': {'color': 'blue'},
'sma5': {'color': 'pink'},
'sma10': {'color': 'yellow'},
'min20': {'color': '#87e470'},
'min50': {'color': '#ac3e2a'},
"min1.1": {'color': 'yellow'},
'sma20': {'color': 'cyan'},
'open_1d': {'color': 'white'},
'close_1d': {'color': 'white'}
},
'subplots': {
# Subplots - each dict defines one additional plot
"BB": {
'bb_width': {'color': 'white'},
'bb_lower_5': {'color': 'yellow'}
},
# "Ind0": {
# buy_crossed_indicator0: {'color': 'green'},
# buy_indicator0: {'color': 'red'}
# },
"Cond": {
'cond1': {'color': 'yellow'},
},
# "Ind1": {
# buy_indicator1: {'color': 'yellow'},
# buy_crossed_indicator1: {'color': 'pink'}
# },
# "Ind2": {
# buy_indicator2: {'color': 'cyan'},
# buy_crossed_indicator2: {'color': 'blue'},
# },
"Rsi": {
'rsi': {'color': 'pink'},
},
"Ecart": {
'normal_var_20': {'color': 'red'},
'normal_var_50': {'color': 'yellow'},
},
# "rolling": {
# 'bb_rolling': {'color': '#87e470'},
# "bb_rolling_min": {'color': '#ac3e2a'}
# },
"percent": {
"percent": {'color': 'green'},
"percent3": {'color': 'blue'},
"percent5": {'color': 'red'},
"distance_min": {'color': 'white'}
}
}
}
# #################### END OF RESULT PLACE ####################
profit_no_change = True
profit_old_sma10 = False
profit_old_sma5 = False
profit_over_rsi = True
profit_quick_gain = True
profit_quick_gain_3 = True
profit_quick_lost = True
profit_short_loss = False
profit_sma5 = True
profit_sma10 = True
profit_sma20 = True
profit_very_old_sma10 = False
trades = list()
# profit_no_change = BooleanParameter(default=True, space="buy")
# profit_quick_lost = BooleanParameter(default=True, space="buy")
# profit_sma10 = BooleanParameter(default=True, space="buy")
# profit_sma20 = BooleanParameter(default=True, space="buy")
# profit_quick_gain = BooleanParameter(default=True, space="buy")
# profit_quick_gain_3 = BooleanParameter(default=True, space="buy")
# profit_old_sma10 = BooleanParameter(default=True, space="buy")
# profit_very_old_sma10 = BooleanParameter(default=True, space="buy")
# profit_over_rsi = BooleanParameter(default=True, space="buy")
# profit_short_loss = BooleanParameter(default=True, space="buy")
# buy_signal_bb_width = DecimalParameter(0.06, 0.15, decimals=2, default=0.065, space='buy')
buy_real_num0 = DecimalParameter(0, 1, decimals=2, default=0.67, space='buy')
buy_real_num1 = DecimalParameter(0, 1, decimals=2, default=0.67, space='buy')
buy_real_num2 = DecimalParameter(0, 2, decimals=2, default=0.67, space='buy')
buy_1_percent_5m_num = DecimalParameter(-0.1, 0.1, decimals=2, default=-0.01, space='buy')
buy_2_percent_5m_num = DecimalParameter(-0.1, 0.1, decimals=2, default=-0.01, space='buy')
buy_3_percent_5m_num = DecimalParameter(-0.1, 0.1, decimals=2, default=-0.01, space='buy')
buy_4_day_week_percent = DecimalParameter(0, 0.1, decimals=2, default=0.01, space='buy')
buy_day_week = CategoricalParameter([
'percent_1d', 'percent3_1d', 'percent5_1d', 'percent_1w', 'percent3_1w'],
default="percent_1d", space='buy')
#buy_3_cond_1h_num = DecimalParameter(0, 2, decimals=2, default=0.67, space='buy')
# buy_1_percent_4h_num = DecimalParameter(-0.1, 0.1, decimals=2, default=0.67, space='buy')
# buy_2_percent_4h_num = DecimalParameter(-0.1, 0.1, decimals=2, default=0.67, space='buy')
# buy_3_percent_4h_num = DecimalParameter(-0.1, 0.1, decimals=2, default=0.67, space='buy')
#buy_3_percent_1d_num = DecimalParameter(-0.1, 0.1, decimals=2, default=0.67, space='buy')
#buy_3_percent_1w_num = DecimalParameter(-0.1, 0.1, decimals=2, default=0.67, space='buy')
buy_min_horizon = IntParameter(50, 200, default=72, space='buy')
#buy_0 = BooleanParameter(default=True, space="buy")
#buy_2 = BooleanParameter(default=True, space="buy")
#buy_3 = BooleanParameter(default=True, space="buy")
buy_0_percent20 = DecimalParameter(-0.1, 0.1, decimals=2, default=-0.02, space='buy')
buy_2_percent20 = DecimalParameter(-0.1, 0.1, decimals=2, default=-0.02, space='buy')
buy_3_percent20 = DecimalParameter(-0.1, 0.1, decimals=2, default=-0.02, space='buy')
buy_0_distance = DecimalParameter(-0.1, 0.1, decimals=2, default=0.02, space='buy')
buy_2_distance = DecimalParameter(-0.1, 0.1, decimals=2, default=0.02, space='buy')
buy_3_distance = DecimalParameter(-0.1, 0.1, decimals=2, default=0.02, space='buy')
buy_decalage_deb_0 = IntParameter(0, 3, default=5, space='buy')
buy_decalage_deb_2 = IntParameter(0, 3, default=5, space='buy')
buy_decalage_deb_3 = IntParameter(0, 3, default=5, space='buy')
buy_decalage0 = IntParameter(buy_decalage_deb_0.value + 1, 8, default=5, space='buy')
buy_decalage2 = IntParameter(buy_decalage_deb_2.value + 1, 8, default=5, space='buy')
buy_decalage3 = IntParameter(buy_decalage_deb_3.value + 1, 8, default=5, space='buy')
buy_1_pente_sma10 = DecimalParameter(0, 0.6, decimals=2, default=0.7, space='buy')
buy_2_pente_sma10 = DecimalParameter(0, 0.6, decimals=2, default=0.7, space='buy')
buy_3_pente_sma10 = DecimalParameter(0, 0.6, decimals=2, default=0.7, space='buy')
buy_4_pente_sma10 = DecimalParameter(0, 0.6, decimals=2, default=0.7, space='buy')
buy_1_pente_sma20 = DecimalParameter(0, 0.6, decimals=2, default=0.7, space='buy')
buy_2_pente_sma20 = DecimalParameter(0, 0.6, decimals=2, default=0.7, space='buy')
buy_3_pente_sma20 = DecimalParameter(0, 0.6, decimals=2, default=0.7, space='buy')
buy_4_pente_sma20 = DecimalParameter(0, 0.6, decimals=2, default=0.7, space='buy')
# buy_1_bb_lower_var_5 = DecimalParameter(0, 0.4, decimals=2, default=0.07, space='buy')
# buy_2_bb_lower_var_5 = DecimalParameter(0, 0.4, decimals=2, default=0.07, space='buy')
# buy_3_bb_lower_var_5 = DecimalParameter(0, 0.4, decimals=2, default=0.07, space='buy')
buy_1_bb_lower_5 = DecimalParameter(0, 0.6, decimals=2, default=0.7, space='buy')
buy_2_bb_lower_5 = DecimalParameter(0, 0.6, decimals=2, default=0.7, space='buy')
buy_3_bb_lower_5 = DecimalParameter(0, 0.6, decimals=2, default=0.7, space='buy')
protection_max_allowed_dd = DecimalParameter(0, 1, decimals=DECIMALS, default=0.04, space='protection')
protection_stop = IntParameter(1, 100, default=48, space='protection')
protection_stoploss_stop = IntParameter(1, 100, default=48, space='protection')
lookback = IntParameter(1, 200, default=48, space='protection')
trade_limit = IntParameter(1, 10, default=2, space='protection')
sell_percent = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')
sell_percent3 = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')
sell_candels = IntParameter(0, 48, default=12, space='sell')
sell_too_old_day = IntParameter(0, 10, default=5, space='sell')
sell_too_old_percent = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')
sell_profit_no_change = DecimalParameter(0, 0.02, decimals=3, default=0.005, space='sell')
sell_profit_percent10 = DecimalParameter(0, 0.002, decimals=4, default=0.001, space='sell')
sell_RSI = IntParameter(70, 98, default=88, space='sell')
sell_RSI2 = IntParameter(70, 98, default=88, space='sell')
sell_RSI2_percent = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')
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:
# {'symbol': 'FTM/USDT', 'timestamp': 1646494199570, 'datetime': '2022-03-05T15:29:59.570Z', 'high': 1.7489,
# 'low': 1.6084, 'bid': 1.6505, 'bidVolume': 2135.0, 'ask': 1.6508, 'askVolume': 2815.0, 'vwap': 1.66852198,
# 'open': 1.7313, 'close': 1.6505, 'last': 1.6505, 'previousClose': '1.73170000', 'change': -0.0808,
# 'percentage': -4.667, 'average': 1.6909, 'baseVolume': 124656725.0, 'quoteVolume': 207992485.7799,
# 'info':
# {'symbol': 'FTMUSDT', 'priceChange': '-0.08080000', 'priceChangePercent': '-4.667',
# 'weightedAvgPrice': '1.66852198', 'prevClosePrice': '1.73170000', 'lastPrice': '1.65050000',
# 'lastQty': '143.00000000', 'bidPrice': '1.65050000', 'bidQty': '2135.00000000',
# 'askPrice': '1.65080000', 'askQty': '2815.00000000', 'openPrice': '1.73130000',
# 'highPrice': '1.74890000', 'lowPrice': '1.60840000', 'volume': '124656725.00000000',
# 'quoteVolume': '207992485.77990000', 'openTime': '1646407799570', 'closeTime': '1646494199570',
# 'firstId': '137149614', 'lastId': '137450289', 'count': '300676'}} - 0.9817468621938484
allow_to_buy = True
max_gain = -100
sum_gain = 0
max_time = 0
if self.dp:
if self.dp.runmode.value in ('live', 'dry_run'):
if len(self.trades) == 0:
print('search')
self.trades = Trade.get_open_trades()
if len(self.trades) >= self.config['max_open_trades'] / 2:
for trade in self.trades:
ticker = self.dp.ticker(trade.pair)
last_price = ticker['last']
gain = (last_price - trade.open_rate) / trade.open_rate
max_gain = max(max_gain, gain)
sum_gain += gain
max_time = max(max_time, datetime.timestamp(trade.open_date))
print(trade.pair, ticker['datetime'], ticker['timestamp'] / 1000, datetime.timestamp(trade.open_date),
datetime.timestamp(trade.open_date) - int(ticker['timestamp'] / 1000))
now = datetime.now()
diff = (datetime.timestamp(now) - max_time / 3600)
if (max_gain <= -0.05) & (len(self.trades) >= self.config['max_open_trades'] / 2) & (diff < 6):
print("allow_to_buy=false")
allow_to_buy = False
print(pair, allow_to_buy, len(self.trades),
"max gain=", max_gain,
"sum_gain=", sum_gain,
"now=", now,
"max=", max_time,
"diff=", datetime.timestamp(now) - max_time)
if allow_to_buy:
self.trades = list()
return allow_to_buy
@property
def protections(self):
return [
{
"method": "CooldownPeriod",
"stop_duration_candles": 10
},
# {
# "method": "MaxDrawdown",
# "lookback_period_candles": self.lookback.value,
# "trade_limit": self.trade_limit.value,
# "stop_duration_candles": self.protection_stop.value,
# "max_allowed_drawdown": self.protection_max_allowed_dd.value,
# "only_per_pair": False
# },
# {
# "method": "StoplossGuard",
# "lookback_period_candles": 24,
# "trade_limit": 4,
# "stop_duration_candles": self.protection_stoploss_stop.value,
# "only_per_pair": False
# },
# {
# "method": "EmergencyStop",
# "min_percent": -0.05,
# "candels": 1
# }
]
def custom_sell(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
current_profit: float, **kwargs):
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
last_candle = dataframe.iloc[-1].squeeze()
previous_last_candle = dataframe.iloc[-2].squeeze()
previous_5_candle = dataframe.iloc[-5].squeeze()
# if (0 < current_profit) & ((current_time - trade.open_date_utc).seconds > 3600) \
# & (last_candle['percent10'] < 0.001):
# return 'small_profit'
#
# if (current_profit > 0.01) \
# & ((previous_last_candle['sma10'] - last_candle['sma10']) / previous_last_candle['sma10'] > 0.003):
# # print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
# return 'sma10_quick'
if (current_profit >= - self.sell_too_old_percent.value) & ((current_time - trade.open_date_utc).days >= self.sell_too_old_day.value)\
& ((current_time - trade.open_date_utc).days < self.sell_too_old_day.value * 2)\
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
return "too_old_0.01"
if (current_profit >= - self.sell_too_old_percent.value * 2) & ((current_time - trade.open_date_utc).days >= self.sell_too_old_day.value * 2)\
& ((current_time - trade.open_date_utc).days < self.sell_too_old_day.value * 3) \
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
return "too_old_0.02"
if (current_profit >= - self.sell_too_old_percent.value * 3) & ((current_time - trade.open_date_utc).days >= self.sell_too_old_day.value * 3) \
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
return "too_old_0.03"
if self.profit_quick_lost and (current_profit >= 0.015) & (last_candle['percent3'] < -0.005):
return "quick_lost"
if self.profit_no_change and (current_profit > self.sell_profit_no_change.value) \
& (last_candle['percent10'] < self.sell_profit_percent10.value) & (last_candle['percent5'] < 0) \
& ((current_time - trade.open_date_utc).seconds >= 3600):
return "no_change"
#if (current_profit > 0.01) & (last_candle['rsi'] < 30):
# return "small_rsi"
# if self.profit_quick_gain_3:
# if (current_profit >= 0.03) & (last_candle['percent3'] < 0) & ((current_time - trade.open_date_utc).seconds <= 3600):
# return "quick_gain_3"
# if self.profit_quick_gain:
# if (0.01 < current_profit < 0.03) & (last_candle['percent3'] < 0) & ((current_time - trade.open_date_utc).seconds <= 3600):
# return "quick_gain"
# if (current_profit > 0 & last_candle['bb_width'] < current_profit):
# return "more_bb_width"
if (current_profit > self.sell_percent.value) & (last_candle['percent3'] < - self.sell_percent3.value) \
& ((current_time - trade.open_date_utc).seconds <= 300 * self.sell_candels.value):
return "quick_gain_param"
if self.profit_sma5:
if (current_profit > 0.01) \
& ((previous_5_candle['sma5'] > last_candle['sma5']) \
| (last_candle['percent3'] < -0.01) | (last_candle['percent5'] < -0.01)) \
& ((last_candle['percent'] < 0) & (last_candle['percent3'] < 0)):
# print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
return 'sma10'
if self.profit_sma10:
if (current_profit > 0.01) \
& ((previous_5_candle['sma10'] > last_candle['sma10']) \
| (last_candle['percent3'] < -0.01) | (last_candle['percent5'] < -0.01)) \
& ((last_candle['percent'] < 0) & (last_candle['percent3'] < 0)):
# print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
return 'sma10'
if self.profit_sma20:
if (current_profit > 0.005) \
& (previous_last_candle['sma10'] > last_candle['sma10']) \
& ((current_time - trade.open_date_utc).seconds >= 3600) \
& ((previous_last_candle['sma20'] > last_candle['sma20']) &
((last_candle['percent5'] < 0) | (last_candle['percent10'] < 0) | (last_candle['percent20'] < 0))):
# print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
return 'sma20'
# if self.profit_old_sma10:
# if (current_profit > 0) \
# & ((current_time - trade.open_date_utc).days >= 3) \
# & ((previous_5_candle['sma10'] > last_candle['sma10']) | (last_candle['percent3'] < -0.005) | (last_candle['percent5'] < -0.005)) \
# & ((last_candle['percent'] < 0) & (last_candle['percent3'] < 0)):
# # print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
# return 'old_sma10'
# if self.profit_very_old_sma10:
# if (current_profit > -0.01) \
# & ((current_time - trade.open_date_utc).days >= 6) \
# & ((previous_5_candle['sma10'] > last_candle['sma10']) | (last_candle['percent3'] < 0) | (last_candle['percent5'] < 0)) \
# & ((last_candle['percent'] < 0) & (last_candle['percent3'] < 0)):
# # print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
# return 'very_old_sma10'
if self.profit_over_rsi:
if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_RSI.value): # & (last_candle['percent'] < 0): #| (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)):
# print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
return 'over_rsi'
if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_RSI2.value) & \
(last_candle['percent'] < - self.sell_RSI2_percent.value): #| (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)):
# print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
return 'over_rsi_2'
if self.profit_short_loss:
if (current_profit > -0.01) & (previous_last_candle['percent10'] > 0.04) & (last_candle['percent'] < 0)\
& ((current_time - trade.open_date_utc).days >= 1): #| (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)):
# print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
return 'short_lost'
# if (current_profit > 0) \
# & (last_candle['rsi'] > 82) & (previous_last_candle['rsi'] > 75): #| (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)):
# # print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
# return 'over_rsi_2'
def informative_pairs(self):
# get access to all pairs available in whitelist.
pairs = self.dp.current_whitelist()
# Assign tf to each pair so they can be downloaded and cached for strategy.
informative_pairs = [(pair, "5m") for pair in pairs]
informative_pairs += [(pair, '1d') for pair in pairs]
informative_pairs += [(pair, '1w') for pair in pairs]
# Optionally Add additional "static" pairs
# informative_pairs = [("BTC/USDT", "1w"), ("BTC/USDT", "1d"), ("BTC/USDT", "5m")]
return informative_pairs
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# dataframe['profit'] = 0
# RSI
dataframe['rsi'] = ta.RSI(dataframe)
dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
dataframe['sma10'] = ta.SMA(dataframe, timeperiod=10)
dataframe['sma20'] = ta.SMA(dataframe, timeperiod=20)
dataframe['sma50'] = ta.SMA(dataframe, timeperiod=50)
dataframe['sma100'] = ta.SMA(dataframe, timeperiod=100)
dataframe["percent"] = (dataframe["close"] - dataframe["open"]) / dataframe["open"]
dataframe["percent5"] = dataframe["percent"].rolling(5).sum()
dataframe["percent3"] = dataframe["percent"].rolling(3).sum()
dataframe["percent10"] = dataframe["percent"].rolling(10).sum()
dataframe["percent20"] = dataframe["percent"].rolling(20).sum()
dataframe["percent50"] = dataframe["percent"].rolling(50).sum()
# if (dataframe["percent50"] < -0.03) & (dataframe['sma10'] > dataframe['sma10'].shift(2)):
# dataframe["percent_ok"] = new dataframe()
# else:
# dataframe["percent_ok"] = 0
dataframe['ecart_20'] = dataframe['close'].rolling(20).var() / dataframe['close']
dataframe['ecart_50'] = dataframe['close'].rolling(50).var() / dataframe['close']
dataframe['min'] = ta.MIN(dataframe['close'], timeperiod=self.buy_min_horizon.value)
dataframe['min10'] = ta.MIN(dataframe['close'], timeperiod=10)
dataframe['min20'] = ta.MIN(dataframe['close'], timeperiod=20)
dataframe['min50'] = ta.MIN(dataframe['close'], timeperiod=50)
dataframe['min200'] = ta.MIN(dataframe['close'], timeperiod=200)
dataframe["volume10"] = dataframe["volume"].rolling(10).mean()
dataframe['max'] = ta.MAX(dataframe['close'], timeperiod=200)
dataframe['max_min'] = dataframe['max'] / dataframe['min']
# Bollinger Bands
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
dataframe['bb_lowerband'] = bollinger['lower']
dataframe['bb_middleband'] = bollinger['mid']
dataframe['bb_upperband'] = bollinger['upper']
dataframe["bb_percent"] = (
(dataframe["close"] - dataframe["bb_lowerband"]) /
(dataframe["bb_upperband"] - dataframe["bb_lowerband"])
)
dataframe["bb_width"] = (
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
)
dataframe['bb_lower_var_5'] = (dataframe['bb_lowerband'] - dataframe['min50']).rolling(5).var()
dataframe['bb_lower_5'] = 100 * ((dataframe['bb_lowerband'].rolling(5).mean() / dataframe['bb_lowerband']) - 1)
# dataframe['bb_min'] = ta.MIN(dataframe['bb_lowerband'], timeperiod=36)
dataframe['distance_min'] = (dataframe['close'] - dataframe['min']) / dataframe['close']
dataframe['min1.1'] = 1.01 * dataframe['min']
dataframe['normal'] = 100 * (dataframe['close'] / dataframe['close'].rolling(200).mean())
dataframe['normal_var_20'] = dataframe['normal'].rolling(20).var()
dataframe['normal_var_50'] = dataframe['normal'].rolling(50).var()
# dataframe['TR'] = ta.TRANGE(dataframe)
# dataframe['ATR'] = ta.SMA(dataframe['TR'], 21)
# Bollinger Bands - Weighted (EMA based instead of SMA)
# weighted_bollinger = qtpylib.weighted_bollinger_bands(
# qtpylib.typical_price(dataframe), window=20, stds=2
# )
# dataframe["wbb_upperband"] = weighted_bollinger["upper"]
# dataframe["wbb_lowerband"] = weighted_bollinger["lower"]
# dataframe["wbb_middleband"] = weighted_bollinger["mid"]
# dataframe["wbb_percent"] = (
# (dataframe["close"] - dataframe["wbb_lowerband"]) /
# (dataframe["wbb_upperband"] - dataframe["wbb_lowerband"])
# )
# dataframe["wbb_width"] = (
# (dataframe["wbb_upperband"] - dataframe["wbb_lowerband"]) / dataframe["wbb_middleband"]
# )
dataframe[buy_crossed_indicator0] = gene_calculator(dataframe, buy_crossed_indicator0)
dataframe[buy_crossed_indicator1] = gene_calculator(dataframe, buy_crossed_indicator1)
dataframe[buy_crossed_indicator2] = gene_calculator(dataframe, buy_crossed_indicator2)
dataframe[buy_indicator0] = gene_calculator(dataframe, buy_indicator0)
dataframe[buy_indicator1] = gene_calculator(dataframe, buy_indicator1)
dataframe[buy_indicator2] = gene_calculator(dataframe, buy_indicator2)
dataframe["cond1"] = dataframe[buy_indicator0].div(dataframe[buy_crossed_indicator0])
# dataframe["dist_min_50"] = dataframe['close'] - dataframe['min50']
# dataframe["dist_min_20"] = dataframe['close'] - dataframe['min20']
# # EMA - Exponential Moving Average
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
# # INFORMATIVE PAIRS
# # Get the informative pair
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1w")
informative["percent"] = (informative["close"] - informative["open"]) / informative["open"]
informative["percent5"] = informative["percent"].rolling(5).sum()
informative["percent3"] = informative["percent"].rolling(3).sum()
# logger.info("Strategy informative using %s %s", "BTC/TUSD", "5m")
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1w", ffill=True)
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="5m")
informative["percent"] = (informative["close"] - informative["open"]) / informative["open"]
informative["percent5"] = informative["percent"].rolling(5).sum()
informative["percent3"] = informative["percent"].rolling(3).sum()
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "5m", ffill=True)
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1d")
informative["percent"] = (informative["close"] - informative["open"]) / informative["open"]
informative["percent5"] = informative["percent"].rolling(5).sum()
informative["percent3"] = informative["percent"].rolling(3).sum()
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1d", ffill=True)
# logger.info("Strategy informative using %s %s", "BTC/TUSD", "1h")
# # Get the informative pair
# informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="4h")
# informative[buy_crossed_indicator0] = gene_calculator(informative, buy_crossed_indicator0)
# informative[buy_indicator0] = gene_calculator(informative, buy_indicator0)
# informative["cond1"] = informative[buy_indicator0].div(informative[buy_crossed_indicator0])
# informative["percent"] = (informative["close"] - informative["open"]) / informative["open"]
# informative["percent5"] = informative["percent"].rolling(5).sum()
# informative["percent3"] = informative["percent"].rolling(3).sum()
# pandas.set_option('display.max_rows', informative.shape[0] + 1)
# pandas.set_option('display.max_columns', 50)
# # print('informative', metadata['pair'], informative.tail(1))
# dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "4h", ffill=True)
# informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe='1d')
# informative[buy_crossed_indicator0] = gene_calculator(informative, buy_crossed_indicator0)
# informative[buy_indicator0] = gene_calculator(informative, buy_indicator0)
# informative["cond1"] = informative[buy_indicator0].div(informative[buy_crossed_indicator0])
# informative["percent"] = (informative["close"] - informative["open"]) / informative["open"]
# informative['max_open'] = ta.MAX(informative["open"], timeperiod=2)
# informative['max_close'] = ta.MIN(informative["close"], timeperiod=2)
# informative["percent5"] = informative["percent"].rolling(5).sum()
# informative["percent3"] = informative["percent"].rolling(3).sum()
# dataframe = merge_informative_pair(dataframe, informative, self.timeframe, '1d', ffill=True)
# informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe='1w')
# informative[buy_crossed_indicator0] = gene_calculator(informative, buy_crossed_indicator0)
# informative[buy_indicator0] = gene_calculator(informative, buy_indicator0)
# informative["cond1"] = informative[buy_indicator0].div(informative[buy_crossed_indicator0])
# informative["percent"] = (informative["close"] - informative["open"]) / informative["open"]
# informative["percent5"] = informative["percent"].rolling(5).sum()
# informative["percent3"] = informative["percent"].rolling(3).sum()
# dataframe = merge_informative_pair(dataframe, informative, self.timeframe, '1w', ffill=True)
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# pandas.set_option('display.max_rows', dataframe.shape[0] + 1)
# pandas.set_option('display.max_columns', 50)
#
# allow_to_buy = True
# max_gain = -100
# trades = Trade.get_open_trades()
#
# if self.dp:
# if self.dp.runmode.value in ('live', 'dry_run'):
# pairs = self.dp.current_whitelist()
# pairs_len = len(pairs)
# pair_index = pairs.index(metadata['pair'])
#
# # print(pair_index, " ", metadata['pair'])
#
# # ob = self.dp.orderbook(metadata['pair'], 1)
# # dataframe['best_bid'] = ob['bids'][0][0]
# # dataframe['best_ask'] = ob['asks'][0][0]
# # print(ob)
#
# for trade in trades:
# # if (metadata['pair'] == trade.pair):
# ticker = self.dp.ticker(trade.pair) #metadata['pair'])
# last_price = ticker['last']
# # dataframe['volume24h'] = ticker['quoteVolume']
# # dataframe['vwap'] = ticker['vwap']
# # d = dataframe.tail(1)
# # print(dataframe)
# gain = (last_price - trade.open_rate) / trade.open_rate
#
# # print("Found open trade: ", trade, " ", ticker['last'], " ", trade.open_rate, gain)
# max_gain = max(max_gain, gain)
#
# if max_gain > - 0.05:
# allow_to_buy = False
#
# # print(metadata['pair'], max_gain, allow_to_buy, len(trades))
# self.protections.global_stop(current_time);
for decalage in range(self.buy_decalage_deb_0.value, self.buy_decalage0.value):
#if self.buy_0.value:
conditions = list()
condition1, dataframe = condition_generator(
dataframe,
buy_operator0,
buy_indicator0,
buy_crossed_indicator0,
self.buy_real_num0.value,
self.buy_decalage0.value
)
conditions.append(condition1)
dataframe.loc[
(
reduce(lambda x, y: x & y, conditions)
& (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= 10)
& (dataframe['sma10'].shift(1) <= dataframe['sma10'])
& (dataframe['close'] < dataframe['bb_middleband'])
& (dataframe['open'] < dataframe['sma10'])
& (dataframe['open'] < dataframe['sma20'])
& (dataframe['min50'].shift(decalage) == dataframe['min50'])
& (dataframe['min10'] <= dataframe['min50'] * 1.02)
& (dataframe['percent20'].shift(decalage) <= self.buy_0_percent20.value)
# & (dataframe['min20'] == dataframe['min50'])
& (dataframe['distance_min'] <= self.buy_0_distance.value)
& ((dataframe['close'] - dataframe['open'].shift(decalage)) / dataframe['open'].shift(decalage) <= 0.005)
# & (dataframe['bb_lower_var_5'] <= self.buy_1_bb_lower_var_5.value)
& (dataframe['bb_lower_5'] <= self.buy_1_bb_lower_5.value)
& (((dataframe['sma10'].shift(1) - dataframe['sma10']) / dataframe['sma10']) < self.buy_1_pente_sma10.value / 100)
& (((dataframe['sma20'].shift(1) - dataframe['sma20']) / dataframe['sma20']) < self.buy_1_pente_sma20.value / 100)
& (dataframe['percent_5m'].shift(1) >= self.buy_1_percent_5m_num.value)
& (dataframe[self.buy_day_week.value] < self.buy_4_day_week_percent.value)
), ['buy', 'buy_tag']] = (1, 'buy_1_' + str(decalage))
for decalage in range(self.buy_decalage_deb_2.value, self.buy_decalage2.value):
#if self.buy_2.value:
dataframe.loc[
(
(dataframe['cond1'].shift(decalage) <= 0.45) #self.buy_real_num0.value / 2)
& (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= 10)
# & (dataframe['sma10'].shift(1) <= dataframe['sma10'])
& (dataframe['close'] < dataframe['sma10'])
& (dataframe['open'] < dataframe['sma20'])
& (dataframe['open'] < dataframe['sma10'])
& (dataframe['min50'].shift(decalage) == dataframe['min50'])
#& (dataframe['min10'] <= dataframe['min50'] * 1.02)
& (dataframe['percent20'].shift(decalage) <= self.buy_2_percent20.value)
# & (dataframe['min20'] == dataframe['min50'])
& (dataframe['distance_min'] <= self.buy_2_distance.value)
& ((dataframe['close'] - dataframe['open'].shift(decalage)) / dataframe['open'].shift(
decalage) <= 0.005)
# & (dataframe['bb_lower_var_5'] <= self.buy_2_bb_lower_var_5.value)
& (dataframe['bb_lower_5'] <= self.buy_2_bb_lower_5.value)
& (((dataframe['sma10'].shift(1) - dataframe['sma10']) / dataframe[
'sma10']) < self.buy_2_pente_sma10.value / 100)
& (((dataframe['sma20'].shift(1) - dataframe['sma20']) / dataframe[
'sma20']) < self.buy_2_pente_sma20.value / 100)
& (dataframe['percent_5m'].shift(1) >= self.buy_2_percent_5m_num.value)
& (dataframe[self.buy_day_week.value] < self.buy_4_day_week_percent.value)
), ['buy', 'buy_tag']] = (1, 'buy_2_' + str(decalage))
for decalage in range(self.buy_decalage_deb_3.value, self.buy_decalage3.value):
#if self.buy_3.value:
dataframe.loc[
(
(dataframe['cond1'].shift(decalage) <= 0.2)
& (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= 10)
# & (dataframe['sma10'].shift(1) <= dataframe['sma10'])
& (dataframe['close'] < dataframe['sma10'])
& (dataframe['open'] < dataframe['sma20'])
& (dataframe['open'] < dataframe['sma10'])
& (dataframe['min50'].shift(decalage) == dataframe['min50'])
#& (dataframe['min10'] <= dataframe['min50'] * 1.02)
& (dataframe['percent20'].shift(decalage) <= self.buy_3_percent20.value)
& (dataframe['distance_min'] <= self.buy_3_distance.value)
& ((dataframe['close'] - dataframe['open'].shift(decalage)) / dataframe['open'].shift(
decalage) <= 0.005)
# & (dataframe['bb_lower_var_5'] <= self.buy_3_bb_lower_var_5.value)
& (dataframe['bb_lower_5'] <= self.buy_3_bb_lower_5.value)
& (((dataframe['sma10'].shift(1) - dataframe['sma10']) / dataframe[
'sma10']) < self.buy_3_pente_sma10.value / 100)
& (((dataframe['sma20'].shift(1) - dataframe['sma20']) / dataframe[
'sma20']) < self.buy_3_pente_sma20.value / 100)
& (dataframe['percent_5m'].shift(1) >= self.buy_3_percent_5m_num.value)
& (dataframe[self.buy_day_week.value] < self.buy_4_day_week_percent.value)
), ['buy', 'buy_tag']] = (1, 'buy_3_' + str(decalage))
# "buy_2_distance": 0.09,
# "buy_2_percent20": 0.05,
decalage = 1
dataframe.loc[
(
(dataframe['cond1'].shift(decalage) <= 0.45) # self.buy_real_num0.value / 2)
& (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= 19)
& (dataframe['close'] < dataframe['sma10'])
& (dataframe['open'] < dataframe['sma100'])
& (dataframe['open'] < dataframe['sma10'])
& (dataframe['min50'].shift(decalage) == dataframe['min50'])
& (dataframe['percent20'].shift(decalage) <= 0.05) #self.buy_2_percent20.value)
& (dataframe['distance_min'] <= 0.09) #self.buy_2_distance.value)
& (dataframe[self.buy_day_week.value] >= self.buy_4_day_week_percent.value)
), ['buy', 'buy_tag']] = (1, 'buy_4_' + str(decalage))
# dataframe.loc[
# (
# (dataframe['close'] < dataframe['close_1d'])
# & (dataframe['close'] > dataframe['bb_upperband'])
# ), ['buy', 'buy_tag']] = (1, 'buy_4')
# pair = metadata['pair']
# allow_to_buy = True
# max_gain = -100
# sum_gain = 0
# max_time = 0
# if len(self.trades) == 0:
# print('search')
# self.trades = Trade.get_open_trades()
#
# # if self.dp:
# # if self.dp.runmode.value in ('live', 'dry_run'):
# if len(self.trades) >= self.config['max_open_trades'] / 2:
# for trade in self.trades:
# ticker = self.dp.ticker(trade.pair)
# last_price = ticker['last']
# gain = (last_price - trade.open_rate) / trade.open_rate
# max_gain = max(max_gain, gain)
# sum_gain += gain
# max_time = max(max_time, datetime.timestamp(trade.open_date))
# print(trade.pair, ticker['datetime'], ticker['timestamp'] / 1000, datetime.timestamp(trade.open_date),
# datetime.timestamp(trade.open_date) - int(ticker['timestamp'] / 1000))
# now = datetime.now()
# diff = (datetime.timestamp(now) - max_time / 3600)
# if (max_gain >= -0.05) & (len(self.trades) >= self.config['max_open_trades'] / 2) & (diff < 6):
# print("allow_to_buy=false")
# allow_to_buy = False
# print(pair, allow_to_buy, len(self.trades),
# "max gain=", max_gain,
# "sum_gain=", sum_gain,
# "now=", now,
# "max=", max_time,
# "diff=", datetime.timestamp(now) - max_time)
#
# if allow_to_buy:
# self.trades = list()
# print(condition1)
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
return dataframe