1011 lines
50 KiB
Python
1011 lines
50 KiB
Python
# Zeus Strategy: First Generation of GodStra Strategy with maximum
|
|
# AVG/MID profit in USDT
|
|
# Author: @Mablue (Masoud Azizi)
|
|
# github: https://github.com/mablue/
|
|
# IMPORTANT: INSTALL TA BEFOUR RUN(pip install ta)
|
|
# freqtrade hyperopt --hyperopt-loss SharpeHyperOptLoss --spaces buy sell roi --strategy Zeus
|
|
# --- 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
|
|
import ta
|
|
from functools import reduce
|
|
import numpy as np
|
|
import talib.abstract as talib
|
|
from freqtrade.strategy.strategy_helper import merge_informative_pair
|
|
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
|
|
|
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'
|
|
|
|
from tabulate import tabulate
|
|
|
|
|
|
def pprint_df(dframe):
|
|
print(tabulate(dframe, headers='keys', tablefmt='psql', showindex=False))
|
|
|
|
|
|
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(talib, gene_name)(
|
|
dataframe
|
|
)
|
|
return normalize(result)
|
|
elif gene_len == 2:
|
|
# print('gene_len == 2\t', indicator)
|
|
gene_timeperiod = int(gene[1])
|
|
result = getattr(talib, 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(talib, 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(talib, gene_name)(
|
|
dataframe,
|
|
timeperiod=gene_timeperiod,
|
|
)
|
|
return normalize(talib.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(talib, gene_name)(
|
|
dataframe,
|
|
timeperiod=gene_timeperiod,
|
|
).iloc[:, gene_index]
|
|
return normalize(talib.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 Zeus_8_3_2_1(IStrategy):
|
|
|
|
# * 1/43: 86 trades. 72/6/8 Wins/Draws/Losses. Avg profit 12.66%. Median profit 11.99%. Total profit 0.10894395 BTC ( 108.94Σ%). Avg duration 3 days, 0:31:00 min. Objective: -48.48793
|
|
# "max_open_trades": 10,
|
|
# "stake_currency": "BTC",
|
|
# "stake_amount": 0.01,
|
|
# "tradable_balance_ratio": 0.99,
|
|
# "timeframe": "4h",
|
|
# "dry_run_wallet": 0.1,
|
|
|
|
# Buy hyperspace params:
|
|
buy_b_params = {
|
|
"buy_b_cat": "<R",
|
|
"buy_b_real": 0.0128,
|
|
}
|
|
|
|
# Sell hyperspace params:
|
|
sell_b_params = {
|
|
"sell_b_cat": "=R",
|
|
"sell_b_real": 0.9455,
|
|
}
|
|
|
|
# Buy hyperspace params:
|
|
buy_h_params = {
|
|
"buy_h_cat": "<R",
|
|
"buy_h_real": 0.0128,
|
|
}
|
|
|
|
# Sell hyperspace params:
|
|
sell_h_params = {
|
|
"sell_h_cat": "=R",
|
|
"sell_h_real": 0.9455,
|
|
}
|
|
|
|
# ROI table:
|
|
minimal_roi = {
|
|
"0": 0.564,
|
|
"567": 0.273,
|
|
"2814": 0.12,
|
|
"7675": 0
|
|
}
|
|
|
|
# Stoploss:
|
|
stoploss = -1 #0.256
|
|
|
|
# sell_h_real = DecimalParameter(0.001, 0.999, decimals=4, default=0.59608, space='sell')
|
|
# sell_h_cat = CategoricalParameter([">R", "=R", "<R"], default='>R', space='sell')
|
|
|
|
# Buy hypers
|
|
timeframe = '5m'
|
|
|
|
market_overview = {'up': 0, 'down': 0}
|
|
market_overview_pct5 = 0
|
|
market_overview_pct1 = 0
|
|
max_open_trades = 5
|
|
max_amount = 40
|
|
|
|
# DCA config
|
|
position_adjustment_enable = True
|
|
#max_dca_orders = 2 # n - 1
|
|
max_dca_multiplier = 7 # (2^n - 1)
|
|
dca_trigger = 0
|
|
|
|
plot_config = {
|
|
"main_plot": {
|
|
"min200": {
|
|
"color": "#86c932"
|
|
},
|
|
"max50": {
|
|
"color": "white"
|
|
},
|
|
"max200": {
|
|
"color": "yellow"
|
|
},
|
|
"sma3_1d": {
|
|
"color": "pink"
|
|
},
|
|
"sma5_1d": {
|
|
"color": "blue"
|
|
},
|
|
"sma10_1d": {
|
|
"color": "orange"
|
|
},
|
|
"close_1d": {
|
|
"color": "#73e233",
|
|
},
|
|
"bb_lowerband": {
|
|
"color": "#da59a6"},
|
|
"bb_upperband": {
|
|
"color": "#da59a6",
|
|
},
|
|
"sar": {
|
|
"color": "#4f9f51",
|
|
},
|
|
"min5_1d": {
|
|
"color": "#6aa123",
|
|
},
|
|
"max5_1d": {
|
|
"color": "red"
|
|
},
|
|
"max3_1d": {
|
|
"color": "blue"
|
|
},
|
|
"close_1d": {
|
|
"color": "green"
|
|
},
|
|
"close_1M": {
|
|
"color": "cyan"
|
|
},
|
|
},
|
|
"subplots": {
|
|
# "Ind": {
|
|
# "trend_ichimoku_base": {
|
|
# "color": "#dd1384"
|
|
# },
|
|
# "trend_kst_diff": {
|
|
# "color": "#850678"
|
|
# }
|
|
# },
|
|
# "BB": {
|
|
# "bb_width": {
|
|
# "color": "white"
|
|
# },
|
|
# "bb_lower_5": {
|
|
# "color": "yellow"
|
|
# }
|
|
# },
|
|
# "Cond": {
|
|
# "cond1": {
|
|
# "color": "yellow"
|
|
# }
|
|
# },
|
|
"Rsi": {
|
|
"rsi": {
|
|
"color": "pink"
|
|
},
|
|
"rsi_1d": {
|
|
"color": "yellow"
|
|
}
|
|
},
|
|
"Percent": {
|
|
"max_min": {
|
|
"color": "#74effc"
|
|
},
|
|
"pct_change_1_1d": {
|
|
"color": "green"
|
|
},
|
|
"pct_change_3_1d": {
|
|
"color": "orange"
|
|
},
|
|
"pct_change_5_1d": {
|
|
"color": "red"
|
|
},
|
|
"sma5_pct": {
|
|
"color": "yellow"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
trades = list()
|
|
|
|
buy_min_horizon = IntParameter(50, 200, default=72, 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_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_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_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')
|
|
|
|
# buy_b_real = DecimalParameter(0.001, 0.999, decimals=4, default=0.11908, space='buy')
|
|
# buy_b_cat = CategoricalParameter([">R", "=R", "<R"], default='<R', space='buy')
|
|
# buy_b_pct = DecimalParameter(0.001, 0.02, decimals=3, default=0.005, space='buy')
|
|
# buy_b_pct_1 = DecimalParameter(-0.2, 0.2, decimals=2, default=0.005, space='buy')
|
|
# buy_b_pct_3 = DecimalParameter(-0.2, 0.2, decimals=2, default=0.005, space='buy')
|
|
# buy_b_pct_5 = DecimalParameter(-0.2, 0.2, decimals=2, default=0.005, space='buy')
|
|
# buy_b_bb_lowerband = DecimalParameter(1, 1.05, default=1, decimals=2, space='buy')
|
|
# buy_b_bb_width = DecimalParameter(0.01, 0.15, default=0.065, decimals=2, space='buy')
|
|
#
|
|
# decalage_h = IntParameter(0, 3, default=0, space='buy')
|
|
# decalage_b = IntParameter(0, 3, default=0, space='buy')
|
|
|
|
# buy_h_real = DecimalParameter(0.001, 0.999, decimals=4, default=0.11908, space='buy')
|
|
# buy_h_cat = CategoricalParameter([">R", "=R", "<R"], default='<R', space='buy')
|
|
# buy_h_pct = DecimalParameter(0.001, 0.02, decimals=3, default=0.005, space='buy')
|
|
# buy_h_pct_1 = DecimalParameter(-0.2, 0.2, decimals=2, default=0.005, space='buy')
|
|
# buy_h_pct_3 = DecimalParameter(-0.2, 0.2, decimals=2, default=0.005, space='buy')
|
|
# buy_h_pct_5 = DecimalParameter(-0.2, 0.2, decimals=2, default=0.005, space='buy')
|
|
# buy_h_bb_lowerband = DecimalParameter(1, 1.05, default=1, decimals=2, space='buy')
|
|
# buy_h_bb_width = DecimalParameter(0.01, 0.15, default=0.065, decimals=2, space='buy')
|
|
|
|
# buy_h_sma = CategoricalParameter(["sma3_1d", "sma5_1d", "sma10_1d"], default='sma10_1d', space='buy')
|
|
# buy_b_sma = CategoricalParameter(["sma3_1d", "sma5_1d", "sma10_1d"], default='sma10_1d', space='buy')
|
|
# buy_h_sma_close = CategoricalParameter(["sma3_1d", "sma5_1d", "sma10_1d"], default='sma3_1d', space='buy')
|
|
# buy_b_sma_close = CategoricalParameter(["sma3_1d", "sma5_1d", "sma10_1d"], default='sma3_1d', space='buy')
|
|
|
|
buy_base = DecimalParameter(0, 0.2, decimals=2, default=0.08, space='buy')
|
|
buy_rsi = IntParameter(20, 90, default=72, space='buy')
|
|
buy_bb_width_n = DecimalParameter(1, 10, decimals=1, default=5, space='buy')
|
|
|
|
buy_min_max_nh = IntParameter(1, 48, default=24, space='buy')
|
|
buy_min_max_n = DecimalParameter(0, 0.2, decimals=2, default=0.05, space='buy')
|
|
buy_min_max_cond1 = DecimalParameter(0, 2, decimals=1, default=1.2, space='buy')
|
|
buy_min_max_rsi = IntParameter(50, 90, default=72, space='buy')
|
|
buy_min_max_coef = DecimalParameter(1, 1.01, decimals=3, default=1.002, space='buy')
|
|
buy_min_max_decalage = IntParameter(2, 10, default=2, space='buy')
|
|
|
|
profit_b_no_change = BooleanParameter(default=True, space="sell")
|
|
profit_b_quick_lost = BooleanParameter(default=True, space="sell")
|
|
profit_b_sma5 = BooleanParameter(default=True, space="sell")
|
|
profit_b_sma10 = BooleanParameter(default=True, space="sell")
|
|
profit_b_sma20 = BooleanParameter(default=True, space="sell")
|
|
profit_b_quick_gain = BooleanParameter(default=True, space="sell")
|
|
profit_b_quick_gain_3 = BooleanParameter(default=True, space="sell")
|
|
profit_b_old_sma10 = BooleanParameter(default=True, space="sell")
|
|
profit_b_very_old_sma10 = BooleanParameter(default=True, space="sell")
|
|
profit_b_over_rsi = BooleanParameter(default=True, space="sell")
|
|
profit_b_short_loss = BooleanParameter(default=True, space="sell")
|
|
|
|
sell_b_percent = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')
|
|
sell_b_percent3 = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')
|
|
sell_b_candels = IntParameter(0, 48, default=12, space='sell')
|
|
|
|
sell_b_too_old_day = IntParameter(0, 10, default=5, space='sell')
|
|
sell_b_too_old_percent = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')
|
|
|
|
sell_b_profit_no_change = DecimalParameter(0, 0.02, decimals=3, default=0.005, space='sell')
|
|
sell_b_profit_percent10 = DecimalParameter(0, 0.002, decimals=4, default=0.001, space='sell')
|
|
|
|
sell_b_RSI = IntParameter(70, 98, default=88, space='sell')
|
|
sell_b_RSI2 = IntParameter(70, 98, default=88, space='sell')
|
|
sell_b_RSI3 = IntParameter(70, 98, default=80, space='sell')
|
|
|
|
sell_b_RSI2_percent = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')
|
|
# sell_b_expected_profit = DecimalParameter(0, 0.01, decimals=3, default=0.01, space='sell')
|
|
|
|
profit_h_no_change = BooleanParameter(default=True, space="sell")
|
|
profit_h_quick_lost = BooleanParameter(default=True, space="sell")
|
|
profit_h_sma5 = BooleanParameter(default=True, space="sell")
|
|
profit_h_sma10 = BooleanParameter(default=True, space="sell")
|
|
profit_h_sma20 = BooleanParameter(default=True, space="sell")
|
|
profit_h_quick_gain = BooleanParameter(default=True, space="sell")
|
|
profit_h_quick_gain_3 = BooleanParameter(default=True, space="sell")
|
|
profit_h_old_sma10 = BooleanParameter(default=True, space="sell")
|
|
profit_h_very_old_sma10 = BooleanParameter(default=True, space="sell")
|
|
profit_h_over_rsi = BooleanParameter(default=True, space="sell")
|
|
profit_h_short_loss = BooleanParameter(default=True, space="sell")
|
|
|
|
sell_h_percent = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')
|
|
sell_h_percent3 = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')
|
|
sell_h_candels = IntParameter(0, 48, default=12, space='sell')
|
|
|
|
sell_h_too_old_day = IntParameter(0, 10, default=5, space='sell')
|
|
sell_h_too_old_percent = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')
|
|
|
|
sell_h_profit_no_change = DecimalParameter(0, 0.02, decimals=3, default=0.005, space='sell')
|
|
sell_h_profit_percent10 = DecimalParameter(0, 0.002, decimals=4, default=0.001, space='sell')
|
|
|
|
sell_h_RSI = IntParameter(70, 98, default=88, space='sell')
|
|
sell_h_RSI2 = IntParameter(70, 98, default=88, space='sell')
|
|
sell_h_RSI3 = IntParameter(70, 98, default=80, space='sell')
|
|
|
|
sell_h_RSI2_percent = DecimalParameter(0, 0.02, decimals=3, default=0.01, space='sell')
|
|
# sell_h_expected_profit = DecimalParameter(0, 0.01, decimals=3, default=0.01, space='sell')
|
|
|
|
# percent_sell = DecimalParameter(-0.1, -0.01, decimals=2, default=-0.08, space="protection")
|
|
hours_sell = IntParameter(5, 48, default=24, space="protection")
|
|
percent_sell_stop = DecimalParameter(-0.8, -0.1, decimals=1, default=-0.8, space="protection")
|
|
|
|
# protection_lost_percent = DecimalParameter(0, 0.2, decimals=2, default=0.06, space='protection')
|
|
# protection_lost_candles = IntParameter(1, 30, default=5, space='protection')
|
|
# protection_percent_buy_lost = IntParameter(1, 10, default=5, space='protection')
|
|
# protection_nb_buy_lost = IntParameter(1, 5, default=2, space='protection')
|
|
# protection_strategy = IntParameter(1, 5, default=1, space='protection')
|
|
# protection_strategy_amount = IntParameter(1, 5, default=2, space='protection')
|
|
|
|
# protection_amount = []
|
|
# protection_amount[1] = self.config['stake_amount']
|
|
# protection_amount[2] = IntParameter(1, 10, default=2, space='protection')
|
|
|
|
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()
|
|
|
|
expected_profit = 0.01
|
|
#print(last_candle['buy_tag'])
|
|
|
|
days = (current_time - trade.open_date_utc).days
|
|
minutes = (current_time - trade.open_date_utc).seconds / 60
|
|
hours = minutes / 60
|
|
######
|
|
|
|
if (current_profit < self.percent_sell_stop.value) & (hours >= self.hours_sell.value) & (last_candle['percent_1h'] <= -0.05):
|
|
return 'sell_stop'
|
|
# if (
|
|
# (btc_last_candle['percent'] < -0.02) | (btc_last_candle['percent5'] < -0.04)) & (current_profit > -0.03):
|
|
# self.stop_buy_for_all = True
|
|
# return "btc_fall"
|
|
|
|
# bb_width_lim = last_candle['bb_width'] / 4
|
|
# bb_width_up = last_candle['bb_upperband'] * (1 - last_candle['bb_width'] / 5)
|
|
|
|
if (last_candle['mrsi3_1h'] <= 0): #(self.market_overview_pct5 < 0) | (last_candle['pct_change_1_4h'] < 0):
|
|
max_percent = 0.004 # last_candle['bb_width'] / 3.5 # 0.005
|
|
max_profit = 0.004 # last_candle['bb_width'] * 3 / 4 # 0.015
|
|
|
|
if (current_profit > 0.01) & \
|
|
(last_candle['percent10'] < -0.005) & ((current_time - trade.open_date_utc).seconds >= 3600):
|
|
return 'b_percent10'
|
|
if (current_profit > max_profit) & \
|
|
((last_candle['percent'] < - max_percent) | (last_candle['percent3'] < -max_percent) | (
|
|
last_candle['percent5'] < -max_percent)):
|
|
return 'b_percent_quick'
|
|
|
|
if (current_profit >= - self.sell_b_too_old_percent.value) & (days >= self.sell_b_too_old_day.value)\
|
|
& (days < self.sell_b_too_old_day.value * 2)\
|
|
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
|
|
return "b_too_old_0.01"
|
|
if (current_profit >= - self.sell_b_too_old_percent.value * 2) & (days >= self.sell_b_too_old_day.value * 2)\
|
|
& (days < self.sell_b_too_old_day.value * 3) \
|
|
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
|
|
return "b_too_old_0.02"
|
|
if (current_profit >= - self.sell_b_too_old_percent.value * 3) & (days >= self.sell_b_too_old_day.value * 3) \
|
|
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
|
|
return "b_too_old_0.03"
|
|
|
|
if self.profit_b_quick_lost.value and (current_profit >= max_profit) & (
|
|
last_candle['percent3'] < -max_percent):
|
|
return "b_quick_lost"
|
|
|
|
if self.profit_b_no_change.value and (current_profit > self.sell_b_profit_no_change.value) \
|
|
& (last_candle['percent10'] < self.sell_b_profit_percent10.value) & (last_candle['percent5'] < 0) \
|
|
& ((current_time - trade.open_date_utc).seconds >= 3600):
|
|
return "b_no_change"
|
|
|
|
if (current_profit > self.sell_b_percent.value) & (last_candle['percent3'] < - self.sell_b_percent3.value) \
|
|
& ((current_time - trade.open_date_utc).seconds <= 300 * self.sell_b_candels.value):
|
|
return "b_quick_gain_param"
|
|
|
|
if self.profit_b_sma5.value:
|
|
if (current_profit > expected_profit) \
|
|
& ((previous_5_candle['sma5'] > last_candle['sma5']) \
|
|
| (last_candle['percent3'] < -expected_profit) | (
|
|
last_candle['percent5'] < -expected_profit)) \
|
|
& ((last_candle['percent'] < 0) & (last_candle['percent3'] < 0)):
|
|
# print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
return 'b_sma5'
|
|
|
|
if self.profit_b_sma10.value:
|
|
if (current_profit > expected_profit) \
|
|
& ((previous_5_candle['sma10'] > last_candle['sma10']) \
|
|
| (last_candle['percent3'] < -expected_profit) | (
|
|
last_candle['percent5'] < -expected_profit)) \
|
|
& ((last_candle['percent'] < 0) & (last_candle['percent3'] < 0)):
|
|
# print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
return 'b_sma10'
|
|
|
|
if self.profit_b_sma20.value:
|
|
if (current_profit > max_percent) \
|
|
& (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 'b_sma20'
|
|
|
|
if self.profit_b_over_rsi.value:
|
|
if (current_profit > 0) & (previous_last_candle[
|
|
'rsi'] > self.sell_b_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 'b_over_rsi'
|
|
|
|
if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_b_RSI2.value) & \
|
|
(last_candle[
|
|
'percent'] < - self.sell_b_RSI2_percent.value): # | (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)):
|
|
# print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
return 'b_over_rsi_2'
|
|
|
|
if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_b_RSI3.value) & \
|
|
(last_candle['close'] >= last_candle['max200']) & (last_candle[
|
|
'percent'] < - self.sell_b_RSI2_percent.value): # | (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)):
|
|
# print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
return 'b_over_rsi_max'
|
|
|
|
if self.profit_b_short_loss.value:
|
|
if (current_profit > -expected_profit) & (previous_last_candle['percent10'] > 0.04) & (
|
|
last_candle['percent'] < 0) \
|
|
& (days >= 1): #| (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)):
|
|
# print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
return 'b_short_lost'
|
|
else:
|
|
max_percent = 0.005 # last_candle['bb_width'] / 3.5 # 0.005
|
|
max_profit = 0.01 # last_candle['bb_width'] * 3 / 4 # 0.015
|
|
|
|
if (current_profit > max_profit) & (
|
|
(last_candle['percent'] < -max_percent) | (last_candle['percent3'] < -max_percent) | (
|
|
last_candle['percent5'] < -max_percent)):
|
|
return 'h_percent_quick'
|
|
|
|
# if (last_candle['bb_width'] < 0.02) & (current_profit > 0) & (last_candle['close'] > bb_width_up) & \
|
|
# ((last_candle['percent'] < - bb_width_lim) | (last_candle['percent3'] < - bb_width_lim) | (last_candle['percent5'] < - bb_width_lim)):
|
|
# return 'h_bb_width_max'
|
|
|
|
if (current_profit >= - self.sell_h_too_old_percent.value) & (days >= self.sell_h_too_old_day.value)\
|
|
& (days < self.sell_h_too_old_day.value * 2)\
|
|
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
|
|
return "h_too_old_0.01"
|
|
if (current_profit >= - self.sell_h_too_old_percent.value * 2) & (days >= self.sell_h_too_old_day.value * 2)\
|
|
& (days < self.sell_h_too_old_day.value * 3) \
|
|
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
|
|
return "h_too_old_0.02"
|
|
if (current_profit >= - self.sell_h_too_old_percent.value * 3) & (days >= self.sell_h_too_old_day.value * 3) \
|
|
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
|
|
return "h_too_old_0.03"
|
|
|
|
if self.profit_h_quick_lost.value and (current_profit >= max_profit) & (
|
|
last_candle['percent3'] < -max_percent):
|
|
return "h_quick_lost"
|
|
|
|
if self.profit_h_no_change.value and (current_profit > self.sell_h_profit_no_change.value) \
|
|
& (last_candle['percent10'] < self.sell_h_profit_percent10.value) & (last_candle['percent5'] < 0) \
|
|
& ((current_time - trade.open_date_utc).seconds >= 3600):
|
|
return "h_no_change"
|
|
|
|
if (current_profit > self.sell_h_percent.value) & (last_candle['percent3'] < - self.sell_h_percent3.value) \
|
|
& ((current_time - trade.open_date_utc).seconds <= 300 * self.sell_h_candels.value):
|
|
return "h_quick_gain_param"
|
|
|
|
if self.profit_h_sma5.value:
|
|
if (current_profit > expected_profit) \
|
|
& ((previous_5_candle['sma5'] > last_candle['sma5']) \
|
|
| (last_candle['percent3'] < -expected_profit) | (
|
|
last_candle['percent5'] < -expected_profit)) \
|
|
& ((last_candle['percent'] < 0) & (last_candle['percent3'] < 0)):
|
|
# print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
return 'h_sma5'
|
|
|
|
if self.profit_h_sma10.value:
|
|
if (current_profit > expected_profit) \
|
|
& ((previous_5_candle['sma10'] > last_candle['sma10']) \
|
|
| (last_candle['percent3'] < -expected_profit) | (
|
|
last_candle['percent5'] < -expected_profit)) \
|
|
& ((last_candle['percent'] < 0) & (last_candle['percent3'] < 0)):
|
|
# print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
return 'h_sma10'
|
|
|
|
if self.profit_h_sma20.value:
|
|
if (current_profit > max_percent) \
|
|
& (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 'h_sma20'
|
|
|
|
if self.profit_h_over_rsi.value:
|
|
if (current_profit > 0) & (previous_last_candle[
|
|
'rsi'] > self.sell_h_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 'h_over_rsi'
|
|
|
|
if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_h_RSI2.value) & \
|
|
(last_candle[
|
|
'percent'] < - self.sell_h_RSI2_percent.value): # | (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)):
|
|
# print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
return 'h_over_rsi_2'
|
|
|
|
if (current_profit > 0) & (previous_last_candle['rsi'] > self.sell_h_RSI3.value) & \
|
|
(last_candle['close'] >= last_candle[
|
|
'max200']): # | (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)):
|
|
# print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
return 'h_over_rsi_max'
|
|
|
|
if self.profit_h_short_loss.value:
|
|
if (current_profit > -expected_profit) & (previous_last_candle['percent10'] > 0.04) & (
|
|
last_candle['percent'] < 0) \
|
|
& (days >= 1): #| (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)):
|
|
# print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
|
|
return 'h_short_lost'
|
|
|
|
def informative_pairs(self):
|
|
# get access to all pairs available in whitelist.
|
|
pairs = self.dp.current_whitelist()
|
|
informative_pairs = [(pair, '1d') for pair in pairs]
|
|
# informative_pairs += [(pair, '1M') for pair in pairs]
|
|
# informative_pairs += [(pair, '4h') for pair in pairs]
|
|
informative_pairs += [(pair, '1h') for pair in pairs]
|
|
|
|
return informative_pairs
|
|
|
|
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
# Add all ta features
|
|
|
|
dataframe['trend_ichimoku_base'] = ta.trend.ichimoku_base_line(
|
|
dataframe['high'],
|
|
dataframe['low'],
|
|
window1=9,
|
|
window2=26,
|
|
visual=False,
|
|
fillna=False
|
|
)
|
|
KST = ta.trend.KSTIndicator(
|
|
close=dataframe['close'],
|
|
roc1=10,
|
|
roc2=15,
|
|
roc3=20,
|
|
roc4=30,
|
|
window1=10,
|
|
window2=10,
|
|
window3=10,
|
|
window4=15,
|
|
nsig=9,
|
|
fillna=False
|
|
)
|
|
|
|
dataframe['trend_kst_diff'] = KST.kst_diff()
|
|
dataframe['pct_change'] = dataframe['close'].pct_change(5)
|
|
dataframe['min'] = talib.MIN(dataframe['close'], timeperiod=self.buy_min_horizon.value)
|
|
dataframe['min10'] = talib.MIN(dataframe['close'], timeperiod=10)
|
|
dataframe['min20'] = talib.MIN(dataframe['close'], timeperiod=20)
|
|
dataframe['min50'] = talib.MIN(dataframe['close'], timeperiod=50)
|
|
dataframe['min200'] = talib.MIN(dataframe['close'], timeperiod=200)
|
|
dataframe['min200_1'] = dataframe['min200'] * 1.005
|
|
dataframe['moy200_12'] = dataframe['min200'].rolling(12).mean()
|
|
dataframe['max50'] = talib.MAX(dataframe['close'], timeperiod=50)
|
|
dataframe['min_max_50'] = (dataframe['max50'] - dataframe['min50']) / dataframe['min50']
|
|
|
|
dataframe['max200'] = talib.MAX(dataframe['close'], timeperiod=200)
|
|
dataframe['min_max200'] = (dataframe['max200'] - dataframe['min200']) / dataframe['min200']
|
|
dataframe['min_n'] = talib.MIN(dataframe['close'], timeperiod=12 * self.buy_min_max_nh.value)
|
|
dataframe['max_n'] = talib.MAX(dataframe['close'], timeperiod=12 * self.buy_min_max_nh.value)
|
|
dataframe['min_max_n'] = (dataframe['max_n'] - dataframe['min_n']) / dataframe['min_n']
|
|
dataframe['rsi'] = talib.RSI(dataframe)
|
|
dataframe['rsi5'] = talib.RSI(dataframe, timeperiod=5)
|
|
dataframe['sma5'] = talib.SMA(dataframe, timeperiod=5)
|
|
dataframe['sma5_inv'] = (dataframe['sma5'].shift(2) > dataframe['sma5'].shift(1)) & (dataframe['sma5'].shift(1) < dataframe['sma5'])
|
|
dataframe['sma5_sell_1'] = (dataframe['sma5'].shift(2) < dataframe['sma5'].shift(1)) & (dataframe['sma5'].shift(1) > dataframe['sma5']) \
|
|
& (
|
|
(dataframe['close'] >= dataframe['max_n']) |
|
|
(dataframe['close'].shift(1) >= dataframe['max_n']) |
|
|
(dataframe['close'].shift(2) >= dataframe['max_n'])
|
|
)
|
|
dataframe['sma5_buy_1'] = (dataframe['sma5'].shift(2) > dataframe['sma5'].shift(1)) & (dataframe['sma5'].shift(1) < dataframe['sma5']) \
|
|
& (
|
|
(dataframe['close'] <= dataframe['min_n']) |
|
|
(dataframe['close'].shift(1) <= dataframe['min_n']) |
|
|
(dataframe['close'].shift(2) <= dataframe['min_n'])
|
|
)
|
|
dataframe['sma5_pct'] = dataframe['sma5'].pct_change(1)
|
|
dataframe['sma10'] = talib.SMA(dataframe, timeperiod=10)
|
|
dataframe['sma20'] = talib.SMA(dataframe, timeperiod=20)
|
|
dataframe['sma50'] = talib.SMA(dataframe, timeperiod=50)
|
|
dataframe['sma100'] = talib.SMA(dataframe, timeperiod=100)
|
|
dataframe["zero"] = 0
|
|
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()
|
|
# dataframe['percent_lost_n'] = dataframe["percent"].rolling(self.protection_lost_candles.value).sum()
|
|
dataframe["volume10"] = dataframe["volume"].rolling(10).mean()
|
|
# 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_lower_width_5'] = (dataframe['bb_lowerband'] * (1 + dataframe['bb_width'] / self.buy_bb_width_n.value))
|
|
|
|
# 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['min_max_close'] = (
|
|
(dataframe['max200'] - dataframe['close']) / (dataframe['close'] - dataframe['min200']))
|
|
dataframe['sar'] = talib.SAR(dataframe)
|
|
# Normalization
|
|
tib = dataframe['trend_ichimoku_base']
|
|
dataframe['trend_ichimoku_base'] = (tib-tib.min())/(tib.max()-tib.min())
|
|
tkd = dataframe['trend_kst_diff']
|
|
dataframe['trend_kst_diff'] = (tkd-tkd.min())/(tkd.max()-tkd.min())
|
|
|
|
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['atr'] = talib.ATR(dataframe, timeperiod=14)
|
|
|
|
################### INFORMATIVE 1D
|
|
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1d")
|
|
informative["rsi"] = talib.RSI(informative)
|
|
informative["max3"] = talib.MAX(informative['close'], timeperiod=3)
|
|
informative["min3"] = talib.MIN(informative['close'], timeperiod=3)
|
|
informative['min5'] = talib.MIN(informative['close'], timeperiod=5)
|
|
informative['max3'] = talib.MAX(informative['close'], timeperiod=3)
|
|
informative['max5'] = talib.MAX(informative['close'], timeperiod=5)
|
|
informative['pct_change_1'] = informative['close'].pct_change(1)
|
|
informative['pct_change_3'] = informative['close'].pct_change(3)
|
|
informative['pct_change_5'] = informative['close'].pct_change(5)
|
|
informative['sma3'] = talib.SMA(informative, timeperiod=3)
|
|
informative['sma5'] = talib.SMA(informative, timeperiod=5)
|
|
informative['sma10'] = talib.SMA(informative, timeperiod=10)
|
|
# informative['sar'] = talib.SAR(informative)
|
|
|
|
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(informative), window=20, stds=2)
|
|
informative['bb_lowerband'] = bollinger['lower']
|
|
informative['bb_middleband'] = bollinger['mid']
|
|
informative['bb_upperband'] = bollinger['upper']
|
|
informative["bb_percent"] = (
|
|
(informative["close"] - informative["bb_lowerband"]) /
|
|
(informative["bb_upperband"] - informative["bb_lowerband"])
|
|
)
|
|
informative["bb_width"] = (
|
|
(informative["bb_upperband"] - informative["bb_lowerband"]) / informative["bb_middleband"]
|
|
)
|
|
|
|
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1d", ffill=True)
|
|
|
|
######################## INFORMATIVE 4h
|
|
# informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="4h")
|
|
# informative["rsi"] = talib.RSI(informative)
|
|
# informative['pct_change_1'] = informative['close'].pct_change(1)
|
|
# informative['pct_change_3'] = informative['close'].pct_change(3)
|
|
# informative['pct_change_5'] = informative['close'].pct_change(5)
|
|
# informative['sma3'] = talib.SMA(informative, timeperiod=3)
|
|
# informative['sma5'] = talib.SMA(informative, timeperiod=5)
|
|
# informative['sma10'] = talib.SMA(informative, timeperiod=10)
|
|
# dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "4h", ffill=True)
|
|
|
|
######################## INFORMATIVE 1h
|
|
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1h")
|
|
informative["rsi"] = talib.RSI(informative)
|
|
informative["mrsi3"] = informative["rsi"].rolling(3).mean()
|
|
informative['percent'] = informative['close'].pct_change(1)
|
|
informative['pct_change_1'] = informative['close'].pct_change(1)
|
|
informative['pct_change_3'] = informative['close'].pct_change(3)
|
|
informative['pct_change_5'] = informative['close'].pct_change(5)
|
|
informative['sma3'] = talib.SMA(informative, timeperiod=3)
|
|
informative['sma5'] = talib.SMA(informative, timeperiod=5)
|
|
informative['sma10'] = talib.SMA(informative, timeperiod=10)
|
|
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1h", ffill=True)
|
|
|
|
################### INFORMATIVE 1M
|
|
# informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1M")
|
|
# dataframe = merge_informative_pair(dataframe, informative, self.timeframe, "1M", ffill=True)
|
|
|
|
# dataframe['support'] = min(dataframe['close_1d'], dataframe['sma3_1d'], dataframe['sma3_1d'])
|
|
return dataframe
|
|
|
|
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
dataframe.loc[
|
|
(
|
|
(dataframe['trend_ichimoku_base'] <= self.buy_base.value)
|
|
& (dataframe['rsi'] < self.buy_rsi.value)
|
|
& (dataframe['close'] < dataframe['sma10'])
|
|
& (dataframe['close'] < dataframe['bb_lower_width_5'])
|
|
# & (dataframe['min50'] == dataframe['min50'].shift(3))
|
|
# & (dataframe['min50'].shift(2) == dataframe['min50'])
|
|
& (dataframe['close'] < dataframe['min_n'] * (1 + dataframe['min_max_50'] / 5) )
|
|
# & (dataframe['close'] <= dataframe['min_200_001'])
|
|
& (dataframe['close'] <= dataframe['close_1h'])
|
|
), ['buy', 'buy_tag']] = (1, 'buy_ichimoku')
|
|
|
|
dataframe.loc[
|
|
(
|
|
(dataframe['min_max_n'] >= self.buy_min_max_n.value)
|
|
& (dataframe['cond1'].shift(self.buy_min_max_decalage.value) <= self.buy_min_max_cond1.value)
|
|
& (dataframe['rsi'] < self.buy_min_max_rsi.value)
|
|
# & (dataframe['close'] < dataframe['min_n'] * self.buy_min_max_coef.value)
|
|
& (dataframe['close'] < dataframe['min_n'] * (1 + dataframe['min_max_50'] / 5))
|
|
& (dataframe['min_n'].shift(self.buy_min_max_decalage.value) == dataframe['min_n'])
|
|
& (dataframe['pct_change_1_1d'] > 0)
|
|
# & (dataframe['close'] <= dataframe['min_200_001'])
|
|
# & (dataframe['min50'] == dataframe['min50'].shift(3))
|
|
# & (dataframe['close'] <= dataframe['close_1d'])
|
|
& (dataframe['close'] <= dataframe['close_1h'])
|
|
), ['buy', 'buy_tag']] = (1, 'buy_min_max')
|
|
|
|
# conditions = [
|
|
# (dataframe['percent10'] <= -0.06)
|
|
# ]
|
|
# # GUARDS AND TRENDS
|
|
# if conditions:
|
|
# dataframe.loc[(reduce(lambda x, y: x & y, conditions)),
|
|
# ['buy', 'buy_tag']] = (1, 'buy_5')
|
|
return dataframe
|
|
|
|
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
|
|
|
return dataframe
|
|
|
|
# def adjust_trade_position(self, trade: Trade, current_time: datetime,
|
|
# current_rate: float, current_profit: float, min_stake: float,
|
|
# max_stake: float, **kwargs):
|
|
# dataframe, _ = self.dp.get_analyzed_dataframe(trade.pair, self.timeframe)
|
|
# if (len(dataframe) < 1):
|
|
# return None
|
|
# last_candle = dataframe.iloc[-1].squeeze()
|
|
# last_candle_5 = dataframe.iloc[-3].squeeze()
|
|
#
|
|
# min_d = min(last_candle['sma3_4h'], last_candle['close_1d'])
|
|
#
|
|
# filled_buys = trade.select_filled_orders('buy')
|
|
# count_of_buys = len(filled_buys)
|
|
# days = (current_time - trade.open_date_utc).days
|
|
# minutes = (current_time - trade.open_date_utc).seconds / 60
|
|
# # condition = (last_candle['cond1'] <= 0.75) & (last_candle['bb_width'] > 0.018) & (
|
|
# # last_candle['rsi'] < 72) & (last_candle['close'] < last_candle['min50'] * 1.006)# & (last_candle['min_max_close'] > 2)
|
|
#
|
|
# condition = (last_candle['min50'] == last_candle_5['min50']) & (last_candle['close'] <= last_candle['close_1h'])
|
|
# p = self.protection_percent_buy_lost.value
|
|
# percents = [p, p * 2, p * 3, p * 4, p * 5, p * 6, p * 7, p * 8, p * 9]
|
|
#
|
|
# if (0 < count_of_buys <= self.protection_nb_buy_lost.value) \
|
|
# & (current_profit < - (percents[count_of_buys - 1] / 100)) & (condition):
|
|
# try:
|
|
# p = self.config['stake_amount']
|
|
# factors = [p, p, p, 2 * p, 3 * p, 4 * p, 5 * p, 6 * p]
|
|
#
|
|
# stake_amount = factors[count_of_buys - 1]# filled_buys[0].cost
|
|
# # This then calculates current safety order size
|
|
# # stake_amount = stake_amount * pow(1.5, count_of_buys)
|
|
# print("-----------" + trade.pair + " " + str(current_profit) + " " + str(count_of_buys) + " " + str(stake_amount) + "---------------------")
|
|
# return stake_amount
|
|
# except Exception as exception:
|
|
# print(exception)
|
|
# return None
|
|
# return None
|