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

1049
BB_RTR_dca.py Normal file

File diff suppressed because it is too large Load Diff

71
BinHV45.py Normal file
View File

@@ -0,0 +1,71 @@
# --- Do not remove these libs ---
from freqtrade.strategy import IStrategy
from freqtrade.strategy import IntParameter
from pandas import DataFrame
import numpy as np
# --------------------------------
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib
def bollinger_bands(stock_price, window_size, num_of_std):
rolling_mean = stock_price.rolling(window=window_size).mean()
rolling_std = stock_price.rolling(window=window_size).std()
lower_band = rolling_mean - (rolling_std * num_of_std)
return rolling_mean, lower_band
class BinHV45(IStrategy):
INTERFACE_VERSION = 2
minimal_roi = {
"0": 0.0125
}
stoploss = -0.05
timeframe = '1m'
buy_bbdelta = IntParameter(low=1, high=15, default=30, space='buy', optimize=True)
buy_closedelta = IntParameter(low=15, high=20, default=30, space='buy', optimize=True)
buy_tail = IntParameter(low=20, high=30, default=30, space='buy', optimize=True)
# Hyperopt parameters
buy_params = {
"buy_bbdelta": 7,
"buy_closedelta": 17,
"buy_tail": 25,
}
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
bollinger = qtpylib.bollinger_bands(dataframe['close'], window=40, stds=2)
dataframe['upper'] = bollinger['upper']
dataframe['mid'] = bollinger['mid']
dataframe['lower'] = bollinger['lower']
dataframe['bbdelta'] = (dataframe['mid'] - dataframe['lower']).abs()
dataframe['pricedelta'] = (dataframe['open'] - dataframe['close']).abs()
dataframe['closedelta'] = (dataframe['close'] - dataframe['close'].shift()).abs()
dataframe['tail'] = (dataframe['close'] - dataframe['low']).abs()
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[
(
dataframe['lower'].shift().gt(0) &
dataframe['bbdelta'].gt(dataframe['close'] * self.buy_bbdelta.value / 1000) &
dataframe['closedelta'].gt(dataframe['close'] * self.buy_closedelta.value / 1000) &
dataframe['tail'].lt(dataframe['bbdelta'] * self.buy_tail.value / 1000) &
dataframe['close'].lt(dataframe['lower'].shift()) &
dataframe['close'].le(dataframe['close'].shift())
),
'buy'] = 1
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
no sell signal
"""
dataframe.loc[:, 'sell'] = 0
return dataframe

67
BreakEven.py Normal file
View File

@@ -0,0 +1,67 @@
# --- Do not remove these libs ---
from freqtrade.strategy.interface import IStrategy
from pandas import DataFrame
# --------------------------------
class BreakEven(IStrategy):
"""
author@: lenik
Sometimes I want to close the bot ASAP, but not have the positions floating around.
I can "/stopbuy" and wait for the positions to get closed by the bot rules, which is
waiting for some profit, etc -- this usually takes too long...
What I would prefer is to close everything that is over 0% profit to avoid the losses.
Here's a simple strategy with empty buy/sell signals and "minimal_roi = { 0 : 0 }" that
sells everything already at profit and wait until the positions at loss will come to break
even point (or the small profit you provide in ROI table).
You may restart the bot with the new strategy as a command-line parameter.
Another way would be to specify the original strategy in the config file, then change to
this one and simply "/reload_config" from the Telegram bot.
"""
# This attribute will be overridden if the config file contains "minimal_roi"
minimal_roi = {
"0": 0.01, # at least 1% at first
"10": 0 # after 10min, everything goes
}
# This is more radical version that sells everything above the profit level
# minimal_roi = {
# "0": 0
# }
# And this is basically "/forcesell all", that sells no matter what profit
# minimal_roi = {
# "0": -1
# }
# Optimal stoploss designed for the strategy
stoploss = -0.05
# Optimal timeframe for the strategy
timeframe = '5m'
# don't generate any buy or sell signals, everything is handled by ROI and stop_loss
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[
(
),
'buy'] = 0
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[
(
),
'sell'] = 0
return dataframe

29
DevilStra.json Normal file
View File

@@ -0,0 +1,29 @@
{
"strategy_name": "DevilStra",
"params": {
"roi": {
"0": 0.574,
"1757": 0.158,
"3804": 0.089,
"6585": 0
},
"stoploss": {
"stoploss": -0.28
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": null,
"trailing_stop_positive_offset": 0.0,
"trailing_only_offset_is_reached": false
},
"buy": {
"buy_spell": "Gu,Ra,Si,Gu,Pa,De,Si,La,Si,De,Cu,Lu,Pa,Si,De,La,Gu,La,Cu,Cu,Zi,Si,Gu,Lu,Pa,Lu,Ra,La,Si,Si,Ra,Lu,Pa,Ra,De,Zi,Ra,Si,De,La,La,Lu,Gu,Lu,Cu,Ra,Cu,Cu,La,Lu,De,Gu,Si,Cu,Cu,La,Si,Ra,Cu,Zi,La,Gu,De,Zi,De,Gu,Pa,Si,Cu,Lu,Gu,Si,Gu,Lu,Ra,De,Lu,Pa,Pa,Si,Zi,Pa,Cu,Ra,Gu,Ra,De,Cu,Lu,De,Pa,Lu,De,Lu,Pa,Gu,Cu,De,La,Ra,Pa,Gu,Lu,Zi,La,Ra,Cu,Si,De,Ra,La,Zi,Lu,Gu,De,Si,Ra,Pa,Si,De,De,La,La,Lu,Cu,La,Lu,Pa,Pa,Pa,De,Lu,La,Zi,Si,Pa,Pa,La,Si,Cu,Ra,Ra,Gu,Zi,Si,Si,La,La,Lu,La,La,Lu,Pa,Lu,Pa,Cu,Lu,Lu,Si,Zi,Lu,Si,Gu,La,La,La,Pa,Ra,Ra,Cu,De,De,Si,De,De,Ra,Pa,Lu,Zi,Cu,Zi,Gu,Zi,Pa,Si,Gu,Zi,La,Ra,La,Zi,Si,Zi,Si,La,La,Zi,Pa,La,Pa,La,Lu,Pa,Si,Zi,Gu,Zi,De,Zi,Ra,Pa,Cu,De,Cu,Ra,Gu,Gu,Zi,Gu,Zi,Cu,Lu,Gu,Zi,Cu,Pa,Gu,Si,Zi,La,Ra,Lu,Pa,Gu,Si,Zi,La,Ra,Pa,Ra,Cu,Cu,Zi,Cu,Gu,De,Lu,De,De,Ra,Cu,Gu,De,Ra,Si,Pa,La,Si,La,Zi,Lu,Zi,Cu,Zi,La,De,Lu,Cu,Zi"
},
"sell": {
"sell_spell": "La,Pa,De,De,La,Si,Si,La,La,La,Si,Pa,Pa,Lu,De,Cu,Cu,Gu,Lu,Ra,Lu,Si,Ra,De,La,Cu,La,La,Gu,La,De,Ra,Ra,Ra,Gu,Lu,Si,Si,Zi,Zi,La,Pa,Pa,Zi,Cu,Gu,Gu,Pa,Gu,Cu,Si,Ra,Ra,La,Gu,De,Si,La,Ra,Pa,Si,Lu,Pa,De,Zi,De,Lu,Si,Gu,De,Lu,De,Ra,Ra,Zi,De,Cu,Zi,Gu,Pa,Ra,De,Pa,De,Pa,Ra,Si,Si,Zi,Cu,Lu,Zi,Ra,De,Ra,Zi,Zi,Pa,Lu,Zi,Cu,Pa,Gu,Pa,Cu,De,Zi,De,De,Pa,Pa,Zi,Lu,Ra,Pa,Ra,Lu,Zi,Gu,Zi,Si,Lu,Ra,Ra,Zi,Lu,Pa,Lu,Si,Pa,Pa,Pa,Si,Zi,La,La,Lu,De,Zi,Gu,Ra,Ra,Ra,Zi,Pa,Zi,Cu,Lu,Gu,Cu,De,Lu,Gu,Lu,Gu,Si,Pa,Pa,Si,La,Gu,Ra,Pa,Si,Si,Si,Cu,Cu,Cu,Si,De,Lu,Gu,Gu,Lu,De,Ra,Gu,Gu,Gu,Cu,La,De,Cu,Zi,Pa,Si,De,Pa,Pa,Pa,La,De,Gu,Zi,La,De,Cu,La,Pa,Ra,Si,Si,Zi,Cu,Ra,Pa,Gu,Pa,Ra,Zi,De,Zi,Gu,Gu,Pa,Cu,Lu,Gu,De,Si,Pa,La,Cu,Zi,Gu,De,Gu,La,Cu,Gu,De,Cu,Cu,Gu,Ra,Lu,Zi,De,La,Ra,Pa,Pa,Si,La,Lu,La,De,De,Ra,De,La,La,Pa,Cu,Lu,Pa,Ra,Pa,Pa,Cu,Zi,Gu,Cu,Gu,La,Si,Ra,Pa"
},
"protection": {}
},
"ft_stratparam_v": 1,
"export_time": "2022-03-04 11:36:44.627014+00:00"
}

721
DevilStra.py Normal file
View File

@@ -0,0 +1,721 @@
# DevilStra Strategy
# 𝔇𝔢𝔳𝔦𝔩 𝔦𝔰 𝔞𝔩𝔴𝔞𝔶𝔰 𝔰𝔱𝔯𝔬𝔫𝔤𝔢𝔯 𝔱𝔥𝔞𝔫 𝔊𝔬𝔡.
# 𝔅𝔲𝔱 𝔱𝔥𝔢 𝔬𝔫𝔩𝔶 𝔬𝔫𝔢 𝔴𝔥𝔬 𝔥𝔞𝔰 𝔱𝔥𝔢 𝔞𝔟𝔦𝔩𝔦𝔱𝔶
# 𝔗𝔬 𝔠𝔯𝔢𝔞𝔱𝔢 𝔫𝔢𝔴 𝔠𝔯𝔢𝔞𝔱𝔲𝔯𝔢𝔰 𝔦𝔰 𝔊𝔬𝔡.
# 𝔄𝔫𝔡 𝔱𝔥𝔢 𝔇𝔢𝔳𝔦𝔩 𝔪𝔞𝔨𝔢𝔰 𝔭𝔬𝔴𝔢𝔯𝔣𝔲𝔩 𝔰𝔭𝔢𝔩𝔩𝔰
# 𝔉𝔯𝔬𝔪 𝔱𝔥𝔦𝔰 𝔰𝔪𝔞𝔩𝔩 𝔠𝔯𝔢𝔞𝔱𝔲𝔯𝔢𝔰 (𝔩𝔦𝔨𝔢 𝔣𝔯𝔬𝔤𝔰, 𝔢𝔱𝔠.)
# 𝔚𝔦𝔱𝔥 𝔣𝔯𝔞𝔤𝔪𝔢𝔫𝔱𝔞𝔱𝔦𝔬𝔫 𝔞𝔫𝔡 𝔪𝔦𝔵𝔦𝔫𝔤 𝔱𝔥𝔢𝔪.
# Author: @Mablue (Masoud Azizi)
# github: https://github.com/mablue/
# * IMPORTANT: You Need An "STATIC" Pairlist On Your Config.json !
# * IMPORTANT: First set PAIR_LIST_LENGHT={pair_whitelist size}
# * And re-hyperopt the Sell strategy And paste result in exact
# * place(lines 535~564)
# freqtrade hyperopt --hyperopt-loss SharpeHyperOptLoss --spaces buy sell -s 𝕯𝖊𝖛𝖎𝖑𝕾𝖙𝖗𝖆
# --- Do not remove these libs ---
import numpy as np
from functools import reduce
import freqtrade.vendor.qtpylib.indicators as qtpylib
import talib.abstract as ta
import random
from freqtrade.strategy.parameters import CategoricalParameter, DecimalParameter, IntParameter
from numpy.lib import math
from freqtrade.strategy.interface import IStrategy
from pandas import DataFrame
# ########################## SETTINGS ##############################
# pairlist lenght(use exact count of pairs you used in whitelist size+1):
PAIR_LIST_LENGHT = 269
# you can find exact value of this inside GodStraNew
TREND_CHECK_CANDLES = 4
# Set the pain range of devil(2~9999)
PAIN_RANGE = 1000
# Add "GodStraNew" Generated Results As spells inside SPELLS.
# Set them unic phonemes like 'Zi' 'Gu' or 'Lu'!
# * Use below replacement on GodStraNew results to
# * Change God Generated Creatures to Spells:
# +-----------------------------+----------------------+
# | GodStraNew Hyperopt Results | DevilStra Spells |
# +-----------------------------+----------------------+
# | | "phonem" : { |
# | buy_params = { | "buy_params" : { |
# | ... | ... |
# | } | }, |
# | sell_params = { | "sell_params" : { |
# | ... | ... |
# | } | } |
# | | }, |
# +-----------------------------+----------------------+
SPELLS = {
"Zi": {
"buy_params": {
"buy_crossed_indicator0": "BOP-4",
"buy_crossed_indicator1": "MACD-0-50",
"buy_crossed_indicator2": "DEMA-52",
"buy_indicator0": "MINUS_DI-50",
"buy_indicator1": "HT_TRENDMODE-50",
"buy_indicator2": "CORREL-128",
"buy_operator0": "/>R",
"buy_operator1": "CA",
"buy_operator2": "CDT",
"buy_real_num0": 0.1763,
"buy_real_num1": 0.6891,
"buy_real_num2": 0.0509,
},
"sell_params": {
"sell_crossed_indicator0": "WCLPRICE-52",
"sell_crossed_indicator1": "AROONOSC-15",
"sell_crossed_indicator2": "CDLRISEFALL3METHODS-52",
"sell_indicator0": "COS-50",
"sell_indicator1": "CDLCLOSINGMARUBOZU-30",
"sell_indicator2": "CDL2CROWS-130",
"sell_operator0": "DT",
"sell_operator1": ">R",
"sell_operator2": "/>R",
"sell_real_num0": 0.0678,
"sell_real_num1": 0.8698,
"sell_real_num2": 0.3917,
}
},
"Gu": {
"buy_params": {
"buy_crossed_indicator0": "SMA-20",
"buy_crossed_indicator1": "CDLLADDERBOTTOM-20",
"buy_crossed_indicator2": "OBV-50",
"buy_indicator0": "MAMA-1-50",
"buy_indicator1": "SUM-40",
"buy_indicator2": "VAR-30",
"buy_operator0": "<R",
"buy_operator1": "D",
"buy_operator2": "D",
"buy_real_num0": 0.2644,
"buy_real_num1": 0.0736,
"buy_real_num2": 0.8954,
},
"sell_params": {
"sell_crossed_indicator0": "CDLLADDERBOTTOM-50",
"sell_crossed_indicator1": "CDLHARAMICROSS-50",
"sell_crossed_indicator2": "CDLDARKCLOUDCOVER-30",
"sell_indicator0": "CDLLADDERBOTTOM-10",
"sell_indicator1": "MAMA-1-40",
"sell_indicator2": "OBV-30",
"sell_operator0": "UT",
"sell_operator1": ">R",
"sell_operator2": "CUT",
"sell_real_num0": 0.2707,
"sell_real_num1": 0.7987,
"sell_real_num2": 0.6891,
}
},
"Lu": {
"buy_params": {
"buy_crossed_indicator0": "HT_SINE-0-28",
"buy_crossed_indicator1": "ADD-130",
"buy_crossed_indicator2": "ADD-12",
"buy_indicator0": "ADD-28",
"buy_indicator1": "AVGPRICE-15",
"buy_indicator2": "AVGPRICE-12",
"buy_operator0": "DT",
"buy_operator1": "D",
"buy_operator2": "C",
"buy_real_num0": 0.3676,
"buy_real_num1": 0.4284,
"buy_real_num2": 0.372,
},
"sell_params": {
"sell_crossed_indicator0": "HT_SINE-0-5",
"sell_crossed_indicator1": "HT_SINE-0-4",
"sell_crossed_indicator2": "HT_SINE-0-28",
"sell_indicator0": "ADD-30",
"sell_indicator1": "AVGPRICE-28",
"sell_indicator2": "ADD-50",
"sell_operator0": "CUT",
"sell_operator1": "DT",
"sell_operator2": "=R",
"sell_real_num0": 0.3205,
"sell_real_num1": 0.2055,
"sell_real_num2": 0.8467,
}
},
"La": {
"buy_params": {
"buy_crossed_indicator0": "WMA-14",
"buy_crossed_indicator1": "MAMA-1-14",
"buy_crossed_indicator2": "CDLHIKKAKE-14",
"buy_indicator0": "T3-14",
"buy_indicator1": "BETA-14",
"buy_indicator2": "HT_PHASOR-1-14",
"buy_operator0": "/>R",
"buy_operator1": ">",
"buy_operator2": ">R",
"buy_real_num0": 0.0551,
"buy_real_num1": 0.3469,
"buy_real_num2": 0.3871,
},
"sell_params": {
"sell_crossed_indicator0": "HT_TRENDLINE-14",
"sell_crossed_indicator1": "LINEARREG-14",
"sell_crossed_indicator2": "STOCHRSI-1-14",
"sell_indicator0": "CDLDARKCLOUDCOVER-14",
"sell_indicator1": "AD-14",
"sell_indicator2": "CDLSTALLEDPATTERN-14",
"sell_operator0": "/=R",
"sell_operator1": "COT",
"sell_operator2": "OT",
"sell_real_num0": 0.3992,
"sell_real_num1": 0.7747,
"sell_real_num2": 0.7415,
}
},
"Si": {
"buy_params": {
"buy_crossed_indicator0": "MACDEXT-2-14",
"buy_crossed_indicator1": "CORREL-14",
"buy_crossed_indicator2": "CMO-14",
"buy_indicator0": "MA-14",
"buy_indicator1": "ADXR-14",
"buy_indicator2": "CDLMARUBOZU-14",
"buy_operator0": "<",
"buy_operator1": "/<R",
"buy_operator2": "<R",
"buy_real_num0": 0.7883,
"buy_real_num1": 0.8286,
"buy_real_num2": 0.6512,
},
"sell_params": {
"sell_crossed_indicator0": "AROON-1-14",
"sell_crossed_indicator1": "STOCHRSI-0-14",
"sell_crossed_indicator2": "SMA-14",
"sell_indicator0": "T3-14",
"sell_indicator1": "AROONOSC-14",
"sell_indicator2": "MIDPOINT-14",
"sell_operator0": "C",
"sell_operator1": "CA",
"sell_operator2": "CB",
"sell_real_num0": 0.372,
"sell_real_num1": 0.5948,
"sell_real_num2": 0.9872,
}
},
"Pa": {
"buy_params": {
"buy_crossed_indicator0": "AROON-0-60",
"buy_crossed_indicator1": "APO-60",
"buy_crossed_indicator2": "BBANDS-0-60",
"buy_indicator0": "WILLR-12",
"buy_indicator1": "AD-15",
"buy_indicator2": "MINUS_DI-12",
"buy_operator0": "D",
"buy_operator1": ">",
"buy_operator2": "CA",
"buy_real_num0": 0.2208,
"buy_real_num1": 0.1371,
"buy_real_num2": 0.6389,
},
"sell_params": {
"sell_crossed_indicator0": "MACDEXT-0-15",
"sell_crossed_indicator1": "BBANDS-2-15",
"sell_crossed_indicator2": "DEMA-15",
"sell_indicator0": "ULTOSC-15",
"sell_indicator1": "MIDPOINT-12",
"sell_indicator2": "PLUS_DI-12",
"sell_operator0": "<",
"sell_operator1": "DT",
"sell_operator2": "COT",
"sell_real_num0": 0.278,
"sell_real_num1": 0.0643,
"sell_real_num2": 0.7065,
}
},
"De": {
"buy_params": {
"buy_crossed_indicator0": "HT_DCPERIOD-12",
"buy_crossed_indicator1": "HT_PHASOR-0-12",
"buy_crossed_indicator2": "MACDFIX-1-15",
"buy_indicator0": "CMO-12",
"buy_indicator1": "TRIMA-12",
"buy_indicator2": "MACDEXT-0-15",
"buy_operator0": "<",
"buy_operator1": "D",
"buy_operator2": "<",
"buy_real_num0": 0.3924,
"buy_real_num1": 0.5546,
"buy_real_num2": 0.7648,
},
"sell_params": {
"sell_crossed_indicator0": "MACDFIX-1-15",
"sell_crossed_indicator1": "MACD-1-15",
"sell_crossed_indicator2": "WMA-15",
"sell_indicator0": "ROC-15",
"sell_indicator1": "MACD-2-15",
"sell_indicator2": "CCI-60",
"sell_operator0": "CA",
"sell_operator1": "<R",
"sell_operator2": "/<R",
"sell_real_num0": 0.4989,
"sell_real_num1": 0.4131,
"sell_real_num2": 0.8904,
}
},
"Ra": {
"buy_params": {
"buy_crossed_indicator0": "EMA-110",
"buy_crossed_indicator1": "SMA-5",
"buy_crossed_indicator2": "SMA-6",
"buy_indicator0": "SMA-6",
"buy_indicator1": "EMA-12",
"buy_indicator2": "EMA-5",
"buy_operator0": "D",
"buy_operator1": "<",
"buy_operator2": "/<R",
"buy_real_num0": 0.9814,
"buy_real_num1": 0.5528,
"buy_real_num2": 0.0541,
},
"sell_params": {
"sell_crossed_indicator0": "SMA-50",
"sell_crossed_indicator1": "EMA-12",
"sell_crossed_indicator2": "SMA-100",
"sell_indicator0": "EMA-110",
"sell_indicator1": "EMA-50",
"sell_indicator2": "EMA-15",
"sell_operator0": "<",
"sell_operator1": "COT",
"sell_operator2": "/=R",
"sell_real_num0": 0.3506,
"sell_real_num1": 0.8767,
"sell_real_num2": 0.0614,
}
},
"Cu": {
"buy_params": {
"buy_crossed_indicator0": "SMA-110",
"buy_crossed_indicator1": "SMA-110",
"buy_crossed_indicator2": "SMA-5",
"buy_indicator0": "SMA-110",
"buy_indicator1": "SMA-55",
"buy_indicator2": "SMA-15",
"buy_operator0": "<R",
"buy_operator1": "<",
"buy_operator2": "CA",
"buy_real_num0": 0.5,
"buy_real_num1": 0.7,
"buy_real_num2": 0.9,
},
"sell_params": {
"sell_crossed_indicator0": "SMA-55",
"sell_crossed_indicator1": "SMA-50",
"sell_crossed_indicator2": "SMA-100",
"sell_indicator0": "SMA-5",
"sell_indicator1": "SMA-50",
"sell_indicator2": "SMA-50",
"sell_operator0": "/=R",
"sell_operator1": "CUT",
"sell_operator2": "DT",
"sell_real_num0": 0.4,
"sell_real_num1": 0.2,
"sell_real_num2": 0.7,
}
}
}
# ######################## END SETTINGS ############################
def spell_finder(index, space):
return SPELLS[index][space+"_params"]
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):
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] > dataframe[crossed_indicator]
)
elif operator == "=":
condition = (
np.isclose(dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "<":
condition = (
dataframe[indicator] < dataframe[crossed_indicator]
)
elif operator == "C":
condition = (
(qtpylib.crossed_below(dataframe[indicator], dataframe[crossed_indicator])) |
(qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator]))
)
elif operator == "CA":
condition = (
qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "CB":
condition = (
qtpylib.crossed_below(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == ">R":
condition = (
dataframe[indicator] > real_num
)
elif operator == "=R":
condition = (
np.isclose(dataframe[indicator], real_num)
)
elif operator == "<R":
condition = (
dataframe[indicator] < real_num
)
elif operator == "/>R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) > real_num
)
elif operator == "/=R":
condition = (
np.isclose(dataframe[indicator].div(
dataframe[crossed_indicator]), real_num)
)
elif operator == "/<R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) < real_num
)
elif operator == "UT":
condition = (
dataframe[indicator] > dataframe[indicator_trend_sma]
)
elif operator == "DT":
condition = (
dataframe[indicator] < dataframe[indicator_trend_sma]
)
elif operator == "OT":
condition = (
np.isclose(dataframe[indicator], dataframe[indicator_trend_sma])
)
elif operator == "CUT":
condition = (
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] > dataframe[indicator_trend_sma]
)
)
elif operator == "CDT":
condition = (
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] < dataframe[indicator_trend_sma]
)
)
elif operator == "COT":
condition = (
(
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) |
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
) &
(
np.isclose(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
)
return condition, dataframe
class DevilStra(IStrategy):
# #################### RESULT PASTE PLACE ####################
# 16/16: 108 trades. 75/18/15 Wins/Draws/Losses. Avg profit 7.77%. Median profit 8.89%. Total profit 0.08404983 BTC ( 84.05Σ%). Avg duration 3 days, 6:49:00 min. Objective: -11.22849
# Buy hyperspace params:
buy_params = {
"buy_spell": "Zi,Lu,Ra,Ra,La,Si,Pa,Si,Cu,La,De,Lu,De,La,Zi,Zi,Zi,Zi,Zi,Lu,Lu,Lu,Si,La,Ra,Pa,La,Zi,Zi,Gu,Ra,De,Gu,Zi,Ra,Ra,Ra,Cu,Pa,De,De,La,Lu,Lu,Lu,La,Zi,Cu,Ra,Gu,Pa,La,Zi,Zi,Si,Lu,Ra,Cu,Cu,Pa,Si,Gu,De,De,Lu,Gu,Zi,Pa,Lu,Pa,Ra,Gu,Cu,La,Pa,Lu,Zi,La,Zi,Gu,Zi,De,Cu,Ra,Lu,Ra,Gu,Si,Ra,La,La,Lu,Gu,Zi,Si,La,Pa,Pa,Cu,Cu,Zi,Gu,Pa,Zi,Pa,Cu,Lu,Pa,Si,De,Gu,Lu,Lu,Cu,Ra,Si,Pa,Gu,Si,Cu,Pa,Zi,Pa,Zi,Gu,Lu,Ra,Pa,Ra,De,Ra,Pa,Zi,La,Pa,De,Pa,Cu,Gu,De,Lu,La,Ra,Zi,Si,Zi,Zi,Cu,Cu,De,Pa,Pa,Zi,De,Ra,La,Lu,De,Lu,Gu,Cu,Cu,La,De,Gu,Lu,Ra,Pa,Lu,Cu,Pa,Pa,De,Si,Zi,Cu,De,De,De,Lu,Si,Zi,Gu,Si,Si,Ra,Pa,Si,La,La,Lu,Lu,De,Gu,Gu,Zi,Ra,La,Lu,Lu,La,Si,Zi,Si,Zi,Si,Lu,Cu,Zi,Lu,De,La,Ra,Ra,Lu,De,Pa,Zi,Gu,Cu,Zi,Pa,De,Si,Lu,De,Cu,De,Zi,Ra,Gu,De,Si,Lu,Lu,Ra,De,Gu,Cu,Gu,La,De,Lu,Lu,Si,Cu,Lu,Zi,Lu,Cu,Gu,Lu,Lu,Ra,Si,Ra,Pa,Lu,De,Ra,Zi,Gu,Gu,Zi,Lu,Cu,Cu,Cu,Lu",
}
# Sell hyperspace params:
sell_params = {
"sell_spell": "La,Pa,De,De,La,Si,Si,La,La,La,Si,Pa,Pa,Lu,De,Cu,Cu,Gu,Lu,Ra,Lu,Si,Ra,De,La,Cu,La,La,Gu,La,De,Ra,Ra,Ra,Gu,Lu,Si,Si,Zi,Zi,La,Pa,Pa,Zi,Cu,Gu,Gu,Pa,Gu,Cu,Si,Ra,Ra,La,Gu,De,Si,La,Ra,Pa,Si,Lu,Pa,De,Zi,De,Lu,Si,Gu,De,Lu,De,Ra,Ra,Zi,De,Cu,Zi,Gu,Pa,Ra,De,Pa,De,Pa,Ra,Si,Si,Zi,Cu,Lu,Zi,Ra,De,Ra,Zi,Zi,Pa,Lu,Zi,Cu,Pa,Gu,Pa,Cu,De,Zi,De,De,Pa,Pa,Zi,Lu,Ra,Pa,Ra,Lu,Zi,Gu,Zi,Si,Lu,Ra,Ra,Zi,Lu,Pa,Lu,Si,Pa,Pa,Pa,Si,Zi,La,La,Lu,De,Zi,Gu,Ra,Ra,Ra,Zi,Pa,Zi,Cu,Lu,Gu,Cu,De,Lu,Gu,Lu,Gu,Si,Pa,Pa,Si,La,Gu,Ra,Pa,Si,Si,Si,Cu,Cu,Cu,Si,De,Lu,Gu,Gu,Lu,De,Ra,Gu,Gu,Gu,Cu,La,De,Cu,Zi,Pa,Si,De,Pa,Pa,Pa,La,De,Gu,Zi,La,De,Cu,La,Pa,Ra,Si,Si,Zi,Cu,Ra,Pa,Gu,Pa,Ra,Zi,De,Zi,Gu,Gu,Pa,Cu,Lu,Gu,De,Si,Pa,La,Cu,Zi,Gu,De,Gu,La,Cu,Gu,De,Cu,Cu,Gu,Ra,Lu,Zi,De,La,Ra,Pa,Pa,Si,La,Lu,La,De,De,Ra,De,La,La,Pa,Cu,Lu,Pa,Ra,Pa,Pa,Cu,Zi,Gu,Cu,Gu,La,Si,Ra,Pa",
}
# ROI table:
minimal_roi = {
"0": 0.574,
"1757": 0.158,
"3804": 0.089,
"6585": 0
}
# Stoploss:
stoploss = -0.28
# #################### END OF RESULT PLACE ####################
# 𝖂𝖔𝖗𝖘𝖙, 𝖀𝖓𝖎𝖉𝖊𝖆𝖑, 𝕾𝖚𝖇𝖔𝖕𝖙𝖎𝖒𝖆𝖑, 𝕸𝖆𝖑𝖆𝖕𝖗𝖔𝖕𝖔𝖘 𝕬𝖓𝖉 𝕯𝖎𝖘𝖒𝖆𝖑 𝖙𝖎𝖒𝖊𝖋𝖗𝖆𝖒𝖊 𝖋𝖔𝖗 𝖙𝖍𝖎𝖘 𝖘𝖙𝖗𝖆𝖙𝖊𝖌𝖞:
timeframe = '4h'
spell_pot = [
",".join(
tuple(
random.choices(
list(SPELLS.keys()),
# TODO: k will be change to len(pairlist)
k=PAIR_LIST_LENGHT
)
)
)for i in range(PAIN_RANGE)
]
buy_spell = CategoricalParameter(
spell_pot, default=spell_pot[0], space='buy')
sell_spell = CategoricalParameter(
spell_pot, default=spell_pot[0], space='sell')
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
pairs = self.dp.current_whitelist()
pairs_len = len(pairs)
pair_index = pairs.index(metadata['pair'])
buy_spells = self.buy_spell.value.split(",")
buy_spells_len = len(buy_spells)
if pairs_len > buy_spells_len:
print(
f"First set PAIR_LIST_LENGHT={pairs_len + 1} And re-hyperopt the")
print("Buy strategy And paste result in exact place(lines 535~564)")
print("IMPORTANT: You Need An 'STATIC' Pairlist On Your Config.json !!!")
exit()
buy_params_index = buy_spells[pair_index]
params = spell_finder(buy_params_index, 'buy')
conditions = list()
# TODO: Its not dry code!
buy_indicator = params['buy_indicator0']
buy_crossed_indicator = params['buy_crossed_indicator0']
buy_operator = params['buy_operator0']
buy_real_num = params['buy_real_num0']
condition, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition)
# backup
buy_indicator = params['buy_indicator1']
buy_crossed_indicator = params['buy_crossed_indicator1']
buy_operator = params['buy_operator1']
buy_real_num = params['buy_real_num1']
condition, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition)
buy_indicator = params['buy_indicator2']
buy_crossed_indicator = params['buy_crossed_indicator2']
buy_operator = params['buy_operator2']
buy_real_num = params['buy_real_num2']
condition, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition)
if conditions:
dataframe.loc[
reduce(lambda x, y: x & y, conditions),
'buy']=1
# print(len(dataframe.keys()))
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
pairs = self.dp.current_whitelist()
pairs_len = len(pairs)
pair_index = pairs.index(metadata['pair'])
sell_spells = self.sell_spell.value.split(",")
sell_spells_len = len(sell_spells)
if pairs_len > sell_spells_len:
print(
f"First set PAIR_LIST_LENGHT={pairs_len + 1} And re-hyperopt the")
print("Sell strategy And paste result in exact place(lines 535~564)")
print("IMPORTANT: You Need An 'STATIC' Pairlist On Your Config.json !!!")
exit()
sell_params_index = sell_spells[pair_index]
params = spell_finder(sell_params_index, 'sell')
conditions = list()
# TODO: Its not dry code!
sell_indicator = params['sell_indicator0']
sell_crossed_indicator = params['sell_crossed_indicator0']
sell_operator = params['sell_operator0']
sell_real_num = params['sell_real_num0']
condition, dataframe = condition_generator(
dataframe,
sell_operator,
sell_indicator,
sell_crossed_indicator,
sell_real_num
)
conditions.append(condition)
sell_indicator = params['sell_indicator1']
sell_crossed_indicator = params['sell_crossed_indicator1']
sell_operator = params['sell_operator1']
sell_real_num = params['sell_real_num1']
condition, dataframe = condition_generator(
dataframe,
sell_operator,
sell_indicator,
sell_crossed_indicator,
sell_real_num
)
conditions.append(condition)
sell_indicator = params['sell_indicator2']
sell_crossed_indicator = params['sell_crossed_indicator2']
sell_operator = params['sell_operator2']
sell_real_num = params['sell_real_num2']
condition, dataframe = condition_generator(
dataframe,
sell_operator,
sell_indicator,
sell_crossed_indicator,
sell_real_num
)
conditions.append(condition)
if conditions:
dataframe.loc[
reduce(lambda x, y: x & y, conditions),
'sell']=1
return dataframe

76
DevilStra.txt Normal file
View File

@@ -0,0 +1,76 @@
Result for strategy DevilStra
============================================================ BACKTESTING REPORT ===========================================================
| Pair | Buys | Avg Profit % | Cum Profit % | Tot Profit USDT | Tot Profit % | Avg Duration | Win Draw Loss Win% |
|-----------+--------+----------------+----------------+-------------------+----------------+-------------------+-------------------------|
| SAND/USDT | 8 | 231.37 | 1850.99 | 1852.839 | 185.28 | 39 days, 21:07:00 | 6 1 1 75.0 |
| SOL/USDT | 135 | 4.65 | 628.37 | 628.998 | 62.90 | 2 days, 6:16:00 | 83 7 45 61.5 |
| AVAX/USDT | 84 | 5.75 | 483.08 | 483.565 | 48.36 | 3 days, 15:04:00 | 63 6 15 75.0 |
| GALA/USDT | 13 | 14.36 | 186.68 | 186.864 | 18.69 | 4 days, 22:32:00 | 9 0 4 69.2 |
| ETH/USDT | 43 | 3.56 | 153.26 | 153.409 | 15.34 | 4 days, 11:59:00 | 32 6 5 74.4 |
| BNB/USDT | 31 | 4.56 | 141.48 | 141.626 | 14.16 | 4 days, 15:44:00 | 18 10 3 58.1 |
| ROSE/USDT | 48 | 2.89 | 138.94 | 139.075 | 13.91 | 3 days, 22:48:00 | 25 15 8 52.1 |
| XRP/USDT | 50 | 1.64 | 82.23 | 82.309 | 8.23 | 3 days, 16:22:00 | 27 8 15 54.0 |
| EGLD/USDT | 44 | 0.08 | 3.35 | 3.355 | 0.34 | 4 days, 7:08:00 | 27 6 11 61.4 |
| ZEC/USDT | 0 | 0.00 | 0.00 | 0.000 | 0.00 | 0:00 | 0 0 0 0 |
| ADA/USDT | 0 | 0.00 | 0.00 | 0.000 | 0.00 | 0:00 | 0 0 0 0 |
| IOTX/USDT | 0 | 0.00 | 0.00 | 0.000 | 0.00 | 0:00 | 0 0 0 0 |
| CELR/USDT | 0 | 0.00 | 0.00 | 0.000 | 0.00 | 0:00 | 0 0 0 0 |
| TRX/USDT | 0 | 0.00 | 0.00 | 0.000 | 0.00 | 0:00 | 0 0 0 0 |
| BTC/USDT | 0 | 0.00 | 0.00 | 0.000 | 0.00 | 0:00 | 0 0 0 0 |
| TOTAL | 456 | 8.04 | 3668.37 | 3672.038 | 367.20 | 4 days, 3:40:00 | 290 59 107 63.6 |
=========================================================== BUY TAG STATS ===========================================================
| TAG | Buys | Avg Profit % | Cum Profit % | Tot Profit USDT | Tot Profit % | Avg Duration | Win Draw Loss Win% |
|-------+--------+----------------+----------------+-------------------+----------------+-----------------+-------------------------|
| TOTAL | 456 | 8.04 | 3668.37 | 3672.038 | 367.20 | 4 days, 3:40:00 | 290 59 107 63.6 |
===================================================== SELL REASON STATS =====================================================
| Sell Reason | Sells | Win Draws Loss Win% | Avg Profit % | Cum Profit % | Tot Profit USDT | Tot Profit % |
|---------------+---------+--------------------------+----------------+----------------+-------------------+----------------|
| roi | 316 | 257 59 0 100 | 16.93 | 5351.22 | 5356.57 | 356.75 |
| sell_signal | 81 | 32 0 49 39.5 | -1.14 | -92.04 | -92.136 | -6.14 |
| stop_loss | 56 | 0 0 56 0 | -28.14 | -1576.06 | -1577.63 | -105.07 |
| force_sell | 3 | 1 0 2 33.3 | -4.92 | -14.75 | -14.763 | -0.98 |
========================================================= LEFT OPEN TRADES REPORT =========================================================
| Pair | Buys | Avg Profit % | Cum Profit % | Tot Profit USDT | Tot Profit % | Avg Duration | Win Draw Loss Win% |
|-----------+--------+----------------+----------------+-------------------+----------------+-------------------+-------------------------|
| EGLD/USDT | 1 | 8.35 | 8.35 | 8.353 | 0.84 | 1 day, 12:00:00 | 1 0 0 100 |
| SOL/USDT | 1 | -10.94 | -10.94 | -10.952 | -1.10 | 8 days, 12:30:00 | 0 0 1 0 |
| XRP/USDT | 1 | -12.15 | -12.15 | -12.165 | -1.22 | 10 days, 12:20:00 | 0 0 1 0 |
| TOTAL | 3 | -4.92 | -14.75 | -14.763 | -1.48 | 6 days, 20:17:00 | 1 0 2 33.3 |
=============== SUMMARY METRICS ================
| Metric | Value |
|------------------------+---------------------|
| Backtesting from | 2021-01-01 00:00:00 |
| Backtesting to | 2021-11-20 00:00:00 |
| Max open trades | 15 |
| | |
| Total/Daily Avg Trades | 456 / 1.41 |
| Starting balance | 1000.000 USDT |
| Final balance | 4672.038 USDT |
| Absolute profit | 3672.038 USDT |
| Total profit % | 367.20% |
| Trades per day | 1.41 |
| Avg. daily profit % | 1.14% |
| Avg. stake amount | 100.000 USDT |
| Total trade volume | 45600.000 USDT |
| | |
| Best Pair | SAND/USDT 1850.99% |
| Worst Pair | ZEC/USDT 0.00% |
| Best trade | SAND/USDT 1576.03% |
| Worst trade | ETH/USDT -28.14% |
| Best day | 1577.608 USDT |
| Worst day | -197.204 USDT |
| Days win/draw/lose | 170 / 98 / 55 |
| Avg. Duration Winners | 3 days, 15:35:00 |
| Avg. Duration Loser | 3 days, 18:33:00 |
| Rejected Buy signals | 0 |
| | |
| Min balance | 1015.800 USDT |
| Max balance | 4686.801 USDT |
| Drawdown | 362.40% |
| Drawdown | 362.761 USDT |
| Drawdown high | 1116.607 USDT |
| Drawdown low | 753.846 USDT |
| Drawdown Start | 2021-05-12 21:55:00 |
| Drawdown End | 2021-06-22 12:45:00 |
| Market change | 2716.79% |
================================================

29
DevilStra2.json Normal file
View File

@@ -0,0 +1,29 @@
{
"strategy_name": "DevilStra2",
"params": {
"roi": {
"0": 0.574,
"1757": 0.158,
"3804": 0.089,
"6585": 0
},
"stoploss": {
"stoploss": -0.28
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": null,
"trailing_stop_positive_offset": 0.0,
"trailing_only_offset_is_reached": false
},
"buy": {
"buy_spell": "De,De,Si,Zi,Si,Ra,Lu,Gu,Ra,Pa,Ra,La,La,Ra,Ra,Zi,La,Gu,De,Ra,Zi,Cu,Cu,La,Lu,Si,Pa,Zi,Zi,Ra,Cu,De,Zi,Zi,Si,Gu,La,Zi,Zi,Gu,Zi,La,Pa,Pa,Gu,Gu,Pa,De,Pa,Lu,La,La,Gu,Ra,Lu,Zi,Pa,Lu,Gu,De,Si,Cu,Gu,La,Zi,Gu,Cu,Si,Pa,La,La,Lu,Cu,Gu,Si,Lu,Ra,De,Si,Lu,Si,La,Si,Cu,De,Lu,Pa,Gu,Pa,Si,Gu,Lu,Lu,Cu,Lu,De,Cu,Pa,De,Pa,Si,Si,Lu,Pa,La,Gu,Pa,Si,Cu,Gu,Zi,La,Lu,Lu,Zi,De,La,La,Zi,La,Gu,Pa,Cu,Pa,Gu,Pa,Gu,Gu,Ra,Lu,Lu,Zi,De,Ra,Lu,La,Lu,De,Si,Lu,Ra,Si,Si,La,Pa,Lu,Zi,Zi,Cu,Cu,Ra,Si,De,Ra,Ra,Lu,La,Zi,De,Pa,Pa,Si,Zi,Gu,De,Gu,Ra,Cu,Pa,Lu,De,Pa,La,Lu,Cu,Ra,Pa,Cu,Cu,Ra,Gu,Zi,La,Si,Zi,La,Si,De,Cu,Ra,Si,Gu,Si,De,Si,Ra,Pa,Gu,Gu,Pa,Si,Zi,Si,Cu,La,Si,De,Cu,Lu,De,Zi,Si,Pa,Gu,Cu,Si,Pa,Gu,De,La,Ra,Pa,Ra,La,Ra,Ra,La,Pa,Ra,La,Cu,De,Lu,Ra,Si,Ra,Cu,Pa,Si,Zi,Gu,De,Cu,De,Lu,Pa,Zi,La,La,La,La,Lu,La,Lu,Cu,Zi,Zi,Zi,La,Si,Ra,De,Lu,Ra,Si,Ra,De,Pa,Lu"
},
"sell": {
"sell_spell": "La,Pa,De,De,La,Si,Si,La,La,La,Si,Pa,Pa,Lu,De,Cu,Cu,Gu,Lu,Ra,Lu,Si,Ra,De,La,Cu,La,La,Gu,La,De,Ra,Ra,Ra,Gu,Lu,Si,Si,Zi,Zi,La,Pa,Pa,Zi,Cu,Gu,Gu,Pa,Gu,Cu,Si,Ra,Ra,La,Gu,De,Si,La,Ra,Pa,Si,Lu,Pa,De,Zi,De,Lu,Si,Gu,De,Lu,De,Ra,Ra,Zi,De,Cu,Zi,Gu,Pa,Ra,De,Pa,De,Pa,Ra,Si,Si,Zi,Cu,Lu,Zi,Ra,De,Ra,Zi,Zi,Pa,Lu,Zi,Cu,Pa,Gu,Pa,Cu,De,Zi,De,De,Pa,Pa,Zi,Lu,Ra,Pa,Ra,Lu,Zi,Gu,Zi,Si,Lu,Ra,Ra,Zi,Lu,Pa,Lu,Si,Pa,Pa,Pa,Si,Zi,La,La,Lu,De,Zi,Gu,Ra,Ra,Ra,Zi,Pa,Zi,Cu,Lu,Gu,Cu,De,Lu,Gu,Lu,Gu,Si,Pa,Pa,Si,La,Gu,Ra,Pa,Si,Si,Si,Cu,Cu,Cu,Si,De,Lu,Gu,Gu,Lu,De,Ra,Gu,Gu,Gu,Cu,La,De,Cu,Zi,Pa,Si,De,Pa,Pa,Pa,La,De,Gu,Zi,La,De,Cu,La,Pa,Ra,Si,Si,Zi,Cu,Ra,Pa,Gu,Pa,Ra,Zi,De,Zi,Gu,Gu,Pa,Cu,Lu,Gu,De,Si,Pa,La,Cu,Zi,Gu,De,Gu,La,Cu,Gu,De,Cu,Cu,Gu,Ra,Lu,Zi,De,La,Ra,Pa,Pa,Si,La,Lu,La,De,De,Ra,De,La,La,Pa,Cu,Lu,Pa,Ra,Pa,Pa,Cu,Zi,Gu,Cu,Gu,La,Si,Ra,Pa"
},
"protection": {}
},
"ft_stratparam_v": 1,
"export_time": "2022-03-04 13:36:54.394335+00:00"
}

658
DevilStra2.py Normal file
View File

@@ -0,0 +1,658 @@
# DevilStra Strategy
# 𝔇𝔢𝔳𝔦𝔩 𝔦𝔰 𝔞𝔩𝔴𝔞𝔶𝔰 𝔰𝔱𝔯𝔬𝔫𝔤𝔢𝔯 𝔱𝔥𝔞𝔫 𝔊𝔬𝔡.
# 𝔅𝔲𝔱 𝔱𝔥𝔢 𝔬𝔫𝔩𝔶 𝔬𝔫𝔢 𝔴𝔥𝔬 𝔥𝔞𝔰 𝔱𝔥𝔢 𝔞𝔟𝔦𝔩𝔦𝔱𝔶
# 𝔗𝔬 𝔠𝔯𝔢𝔞𝔱𝔢 𝔫𝔢𝔴 𝔠𝔯𝔢𝔞𝔱𝔲𝔯𝔢𝔰 𝔦𝔰 𝔊𝔬𝔡.
# 𝔄𝔫𝔡 𝔱𝔥𝔢 𝔇𝔢𝔳𝔦𝔩 𝔪𝔞𝔨𝔢𝔰 𝔭𝔬𝔴𝔢𝔯𝔣𝔲𝔩 𝔰𝔭𝔢𝔩𝔩𝔰
# 𝔉𝔯𝔬𝔪 𝔱𝔥𝔦𝔰 𝔰𝔪𝔞𝔩𝔩 𝔠𝔯𝔢𝔞𝔱𝔲𝔯𝔢𝔰 (𝔩𝔦𝔨𝔢 𝔣𝔯𝔬𝔤𝔰, 𝔢𝔱𝔠.)
# 𝔚𝔦𝔱𝔥 𝔣𝔯𝔞𝔤𝔪𝔢𝔫𝔱𝔞𝔱𝔦𝔬𝔫 𝔞𝔫𝔡 𝔪𝔦𝔵𝔦𝔫𝔤 𝔱𝔥𝔢𝔪.
# Author: @Mablue (Masoud Azizi)
# github: https://github.com/mablue/
# * IMPORTANT: You Need An "STATIC" Pairlist On Your Config.json !
# * IMPORTANT: First set PAIR_LIST_LENGHT={pair_whitelist size}
# * And re-hyperopt the Sell strategy And paste result in exact
# * place(lines 535~564)
# freqtrade hyperopt --hyperopt-loss SharpeHyperOptLoss --spaces buy sell -s 𝕯𝖊𝖛𝖎𝖑𝕾𝖙𝖗𝖆
# --- Do not remove these libs ---
import numpy as np
from functools import reduce
import freqtrade.vendor.qtpylib.indicators as qtpylib
import talib.abstract as ta
import random
from freqtrade.strategy.parameters import CategoricalParameter, DecimalParameter, IntParameter
from numpy.lib import math
from freqtrade.strategy.interface import IStrategy
from pandas import DataFrame
# ########################## SETTINGS ##############################
# pairlist lenght(use exact count of pairs you used in whitelist size+1):
PAIR_LIST_LENGHT = 269
# you can find exact value of this inside GodStraNew
TREND_CHECK_CANDLES = 4
# Set the pain range of devil(2~9999)
PAIN_RANGE = 1000
# Add "GodStraNew" Generated Results As spells inside SPELLS.
# Set them unic phonemes like 'Zi' 'Gu' or 'Lu'!
# * Use below replacement on GodStraNew results to
# * Change God Generated Creatures to Spells:
# +-----------------------------+----------------------+
# | GodStraNew Hyperopt Results | DevilStra Spells |
# +-----------------------------+----------------------+
# | | "phonem" : { |
# | buy_params = { | "buy_params" : { |
# | ... | ... |
# | } | }, |
# | sell_params = { | "sell_params" : { |
# | ... | ... |
# | } | } |
# | | }, |
# +-----------------------------+----------------------+
SPELLS = {
"Zi": {
"buy_params": {
"buy_crossed_indicator0": "BOP-4",
"buy_crossed_indicator1": "MACD-0-50",
"buy_crossed_indicator2": "DEMA-52",
"buy_indicator0": "MINUS_DI-50",
"buy_indicator1": "HT_TRENDMODE-50",
"buy_indicator2": "CORREL-128",
"buy_operator0": "/>R",
"buy_operator1": "CA",
"buy_operator2": "CDT",
"buy_real_num0": 0.1763,
"buy_real_num1": 0.6891,
"buy_real_num2": 0.0509,
},
"sell_params": {
"sell_crossed_indicator0": "WCLPRICE-52",
"sell_crossed_indicator1": "AROONOSC-15",
"sell_crossed_indicator2": "CDLRISEFALL3METHODS-52",
"sell_indicator0": "COS-50",
"sell_indicator1": "CDLCLOSINGMARUBOZU-30",
"sell_indicator2": "CDL2CROWS-130",
"sell_operator0": "DT",
"sell_operator1": ">R",
"sell_operator2": "/>R",
"sell_real_num0": 0.0678,
"sell_real_num1": 0.8698,
"sell_real_num2": 0.3917,
}
},
"Gu": {
"buy_params": {
"buy_crossed_indicator0": "SMA-20",
"buy_crossed_indicator1": "CDLLADDERBOTTOM-20",
"buy_crossed_indicator2": "OBV-50",
"buy_indicator0": "MAMA-1-50",
"buy_indicator1": "SUM-40",
"buy_indicator2": "VAR-30",
"buy_operator0": "<R",
"buy_operator1": "D",
"buy_operator2": "D",
"buy_real_num0": 0.2644,
"buy_real_num1": 0.0736,
"buy_real_num2": 0.8954,
},
"sell_params": {
"sell_crossed_indicator0": "CDLLADDERBOTTOM-50",
"sell_crossed_indicator1": "CDLHARAMICROSS-50",
"sell_crossed_indicator2": "CDLDARKCLOUDCOVER-30",
"sell_indicator0": "CDLLADDERBOTTOM-10",
"sell_indicator1": "MAMA-1-40",
"sell_indicator2": "OBV-30",
"sell_operator0": "UT",
"sell_operator1": ">R",
"sell_operator2": "CUT",
"sell_real_num0": 0.2707,
"sell_real_num1": 0.7987,
"sell_real_num2": 0.6891,
}
},
"Lu": {
"buy_params": {
"buy_crossed_indicator0": "HT_SINE-0-28",
"buy_crossed_indicator1": "ADD-130",
"buy_crossed_indicator2": "ADD-12",
"buy_indicator0": "ADD-28",
"buy_indicator1": "AVGPRICE-15",
"buy_indicator2": "AVGPRICE-12",
"buy_operator0": "DT",
"buy_operator1": "D",
"buy_operator2": "C",
"buy_real_num0": 0.3676,
"buy_real_num1": 0.4284,
"buy_real_num2": 0.372,
},
"sell_params": {
"sell_crossed_indicator0": "HT_SINE-0-5",
"sell_crossed_indicator1": "HT_SINE-0-4",
"sell_crossed_indicator2": "HT_SINE-0-28",
"sell_indicator0": "ADD-30",
"sell_indicator1": "AVGPRICE-28",
"sell_indicator2": "ADD-50",
"sell_operator0": "CUT",
"sell_operator1": "DT",
"sell_operator2": "=R",
"sell_real_num0": 0.3205,
"sell_real_num1": 0.2055,
"sell_real_num2": 0.8467,
}
},
"La": {
"buy_params": {
"buy_crossed_indicator0": "WMA-14",
"buy_crossed_indicator1": "MAMA-1-14",
"buy_crossed_indicator2": "CDLHIKKAKE-14",
"buy_indicator0": "T3-14",
"buy_indicator1": "BETA-14",
"buy_indicator2": "HT_PHASOR-1-14",
"buy_operator0": "/>R",
"buy_operator1": ">",
"buy_operator2": ">R",
"buy_real_num0": 0.0551,
"buy_real_num1": 0.3469,
"buy_real_num2": 0.3871,
},
"sell_params": {
"sell_crossed_indicator0": "HT_TRENDLINE-14",
"sell_crossed_indicator1": "LINEARREG-14",
"sell_crossed_indicator2": "STOCHRSI-1-14",
"sell_indicator0": "CDLDARKCLOUDCOVER-14",
"sell_indicator1": "AD-14",
"sell_indicator2": "CDLSTALLEDPATTERN-14",
"sell_operator0": "/=R",
"sell_operator1": "COT",
"sell_operator2": "OT",
"sell_real_num0": 0.3992,
"sell_real_num1": 0.7747,
"sell_real_num2": 0.7415,
}
},
"Si": {
"buy_params": {
"buy_crossed_indicator0": "MACDEXT-2-14",
"buy_crossed_indicator1": "CORREL-14",
"buy_crossed_indicator2": "CMO-14",
"buy_indicator0": "MA-14",
"buy_indicator1": "ADXR-14",
"buy_indicator2": "CDLMARUBOZU-14",
"buy_operator0": "<",
"buy_operator1": "/<R",
"buy_operator2": "<R",
"buy_real_num0": 0.7883,
"buy_real_num1": 0.8286,
"buy_real_num2": 0.6512,
},
"sell_params": {
"sell_crossed_indicator0": "AROON-1-14",
"sell_crossed_indicator1": "STOCHRSI-0-14",
"sell_crossed_indicator2": "SMA-14",
"sell_indicator0": "T3-14",
"sell_indicator1": "AROONOSC-14",
"sell_indicator2": "MIDPOINT-14",
"sell_operator0": "C",
"sell_operator1": "CA",
"sell_operator2": "CB",
"sell_real_num0": 0.372,
"sell_real_num1": 0.5948,
"sell_real_num2": 0.9872,
}
},
"Pa": {
"buy_params": {
"buy_crossed_indicator0": "AROON-0-60",
"buy_crossed_indicator1": "APO-60",
"buy_crossed_indicator2": "BBANDS-0-60",
"buy_indicator0": "WILLR-12",
"buy_indicator1": "AD-15",
"buy_indicator2": "MINUS_DI-12",
"buy_operator0": "D",
"buy_operator1": ">",
"buy_operator2": "CA",
"buy_real_num0": 0.2208,
"buy_real_num1": 0.1371,
"buy_real_num2": 0.6389,
},
"sell_params": {
"sell_crossed_indicator0": "MACDEXT-0-15",
"sell_crossed_indicator1": "BBANDS-2-15",
"sell_crossed_indicator2": "DEMA-15",
"sell_indicator0": "ULTOSC-15",
"sell_indicator1": "MIDPOINT-12",
"sell_indicator2": "PLUS_DI-12",
"sell_operator0": "<",
"sell_operator1": "DT",
"sell_operator2": "COT",
"sell_real_num0": 0.278,
"sell_real_num1": 0.0643,
"sell_real_num2": 0.7065,
}
},
"De": {
"buy_params": {
"buy_crossed_indicator0": "HT_DCPERIOD-12",
"buy_crossed_indicator1": "HT_PHASOR-0-12",
"buy_crossed_indicator2": "MACDFIX-1-15",
"buy_indicator0": "CMO-12",
"buy_indicator1": "TRIMA-12",
"buy_indicator2": "MACDEXT-0-15",
"buy_operator0": "<",
"buy_operator1": "D",
"buy_operator2": "<",
"buy_real_num0": 0.3924,
"buy_real_num1": 0.5546,
"buy_real_num2": 0.7648,
},
"sell_params": {
"sell_crossed_indicator0": "MACDFIX-1-15",
"sell_crossed_indicator1": "MACD-1-15",
"sell_crossed_indicator2": "WMA-15",
"sell_indicator0": "ROC-15",
"sell_indicator1": "MACD-2-15",
"sell_indicator2": "CCI-60",
"sell_operator0": "CA",
"sell_operator1": "<R",
"sell_operator2": "/<R",
"sell_real_num0": 0.4989,
"sell_real_num1": 0.4131,
"sell_real_num2": 0.8904,
}
},
"Ra": {
"buy_params": {
"buy_crossed_indicator0": "EMA-110",
"buy_crossed_indicator1": "SMA-5",
"buy_crossed_indicator2": "SMA-6",
"buy_indicator0": "SMA-6",
"buy_indicator1": "EMA-12",
"buy_indicator2": "EMA-5",
"buy_operator0": "D",
"buy_operator1": "<",
"buy_operator2": "/<R",
"buy_real_num0": 0.9814,
"buy_real_num1": 0.5528,
"buy_real_num2": 0.0541,
},
"sell_params": {
"sell_crossed_indicator0": "SMA-50",
"sell_crossed_indicator1": "EMA-12",
"sell_crossed_indicator2": "SMA-100",
"sell_indicator0": "EMA-110",
"sell_indicator1": "EMA-50",
"sell_indicator2": "EMA-15",
"sell_operator0": "<",
"sell_operator1": "COT",
"sell_operator2": "/=R",
"sell_real_num0": 0.3506,
"sell_real_num1": 0.8767,
"sell_real_num2": 0.0614,
}
},
"Cu": {
"buy_params": {
"buy_crossed_indicator0": "SMA-110",
"buy_crossed_indicator1": "SMA-110",
"buy_crossed_indicator2": "SMA-5",
"buy_indicator0": "SMA-110",
"buy_indicator1": "SMA-55",
"buy_indicator2": "SMA-15",
"buy_operator0": "<R",
"buy_operator1": "<",
"buy_operator2": "CA",
"buy_real_num0": 0.5,
"buy_real_num1": 0.7,
"buy_real_num2": 0.9,
},
"sell_params": {
"sell_crossed_indicator0": "SMA-55",
"sell_crossed_indicator1": "SMA-50",
"sell_crossed_indicator2": "SMA-100",
"sell_indicator0": "SMA-5",
"sell_indicator1": "SMA-50",
"sell_indicator2": "SMA-50",
"sell_operator0": "/=R",
"sell_operator1": "CUT",
"sell_operator2": "DT",
"sell_real_num0": 0.4,
"sell_real_num1": 0.2,
"sell_real_num2": 0.7,
}
}
}
# ######################## END SETTINGS ############################
def spell_finder(index, space):
return SPELLS[index][space+"_params"]
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):
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] > dataframe[crossed_indicator]
)
elif operator == "=":
condition = (
np.isclose(dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "<":
condition = (
dataframe[indicator] < dataframe[crossed_indicator]
)
elif operator == "C":
condition = (
(qtpylib.crossed_below(dataframe[indicator], dataframe[crossed_indicator])) |
(qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator]))
)
elif operator == "CA":
condition = (
qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "CB":
condition = (
qtpylib.crossed_below(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == ">R":
condition = (
dataframe[indicator] > real_num
)
elif operator == "=R":
condition = (
np.isclose(dataframe[indicator], real_num)
)
elif operator == "<R":
condition = (
dataframe[indicator] < real_num
)
elif operator == "/>R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) > real_num
)
elif operator == "/=R":
condition = (
np.isclose(dataframe[indicator].div(
dataframe[crossed_indicator]), real_num)
)
elif operator == "/<R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) < real_num
)
elif operator == "UT":
condition = (
dataframe[indicator] > dataframe[indicator_trend_sma]
)
elif operator == "DT":
condition = (
dataframe[indicator] < dataframe[indicator_trend_sma]
)
elif operator == "OT":
condition = (
np.isclose(dataframe[indicator], dataframe[indicator_trend_sma])
)
elif operator == "CUT":
condition = (
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] > dataframe[indicator_trend_sma]
)
)
elif operator == "CDT":
condition = (
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] < dataframe[indicator_trend_sma]
)
)
elif operator == "COT":
condition = (
(
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) |
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
) &
(
np.isclose(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
)
return condition, dataframe
class DevilStra2(IStrategy):
# #################### RESULT PASTE PLACE ####################
# 16/16: 108 trades. 75/18/15 Wins/Draws/Losses. Avg profit 7.77%. Median profit 8.89%. Total profit 0.08404983 BTC ( 84.05Σ%). Avg duration 3 days, 6:49:00 min. Objective: -11.22849
# Buy hyperspace params:
buy_params = {
"buy_spell": "Zi,Lu,Ra,Ra,La,Si,Pa,Si,Cu,La,De,Lu,De,La,Zi,Zi,Zi,Zi,Zi,Lu,Lu,Lu,Si,La,Ra,Pa,La,Zi,Zi,Gu,Ra,De,Gu,Zi,Ra,Ra,Ra,Cu,Pa,De,De,La,Lu,Lu,Lu,La,Zi,Cu,Ra,Gu,Pa,La,Zi,Zi,Si,Lu,Ra,Cu,Cu,Pa,Si,Gu,De,De,Lu,Gu,Zi,Pa,Lu,Pa,Ra,Gu,Cu,La,Pa,Lu,Zi,La,Zi,Gu,Zi,De,Cu,Ra,Lu,Ra,Gu,Si,Ra,La,La,Lu,Gu,Zi,Si,La,Pa,Pa,Cu,Cu,Zi,Gu,Pa,Zi,Pa,Cu,Lu,Pa,Si,De,Gu,Lu,Lu,Cu,Ra,Si,Pa,Gu,Si,Cu,Pa,Zi,Pa,Zi,Gu,Lu,Ra,Pa,Ra,De,Ra,Pa,Zi,La,Pa,De,Pa,Cu,Gu,De,Lu,La,Ra,Zi,Si,Zi,Zi,Cu,Cu,De,Pa,Pa,Zi,De,Ra,La,Lu,De,Lu,Gu,Cu,Cu,La,De,Gu,Lu,Ra,Pa,Lu,Cu,Pa,Pa,De,Si,Zi,Cu,De,De,De,Lu,Si,Zi,Gu,Si,Si,Ra,Pa,Si,La,La,Lu,Lu,De,Gu,Gu,Zi,Ra,La,Lu,Lu,La,Si,Zi,Si,Zi,Si,Lu,Cu,Zi,Lu,De,La,Ra,Ra,Lu,De,Pa,Zi,Gu,Cu,Zi,Pa,De,Si,Lu,De,Cu,De,Zi,Ra,Gu,De,Si,Lu,Lu,Ra,De,Gu,Cu,Gu,La,De,Lu,Lu,Si,Cu,Lu,Zi,Lu,Cu,Gu,Lu,Lu,Ra,Si,Ra,Pa,Lu,De,Ra,Zi,Gu,Gu,Zi,Lu,Cu,Cu,Cu,Lu",
}
# Sell hyperspace params:
sell_params = {
"sell_spell": "La,Pa,De,De,La,Si,Si,La,La,La,Si,Pa,Pa,Lu,De,Cu,Cu,Gu,Lu,Ra,Lu,Si,Ra,De,La,Cu,La,La,Gu,La,De,Ra,Ra,Ra,Gu,Lu,Si,Si,Zi,Zi,La,Pa,Pa,Zi,Cu,Gu,Gu,Pa,Gu,Cu,Si,Ra,Ra,La,Gu,De,Si,La,Ra,Pa,Si,Lu,Pa,De,Zi,De,Lu,Si,Gu,De,Lu,De,Ra,Ra,Zi,De,Cu,Zi,Gu,Pa,Ra,De,Pa,De,Pa,Ra,Si,Si,Zi,Cu,Lu,Zi,Ra,De,Ra,Zi,Zi,Pa,Lu,Zi,Cu,Pa,Gu,Pa,Cu,De,Zi,De,De,Pa,Pa,Zi,Lu,Ra,Pa,Ra,Lu,Zi,Gu,Zi,Si,Lu,Ra,Ra,Zi,Lu,Pa,Lu,Si,Pa,Pa,Pa,Si,Zi,La,La,Lu,De,Zi,Gu,Ra,Ra,Ra,Zi,Pa,Zi,Cu,Lu,Gu,Cu,De,Lu,Gu,Lu,Gu,Si,Pa,Pa,Si,La,Gu,Ra,Pa,Si,Si,Si,Cu,Cu,Cu,Si,De,Lu,Gu,Gu,Lu,De,Ra,Gu,Gu,Gu,Cu,La,De,Cu,Zi,Pa,Si,De,Pa,Pa,Pa,La,De,Gu,Zi,La,De,Cu,La,Pa,Ra,Si,Si,Zi,Cu,Ra,Pa,Gu,Pa,Ra,Zi,De,Zi,Gu,Gu,Pa,Cu,Lu,Gu,De,Si,Pa,La,Cu,Zi,Gu,De,Gu,La,Cu,Gu,De,Cu,Cu,Gu,Ra,Lu,Zi,De,La,Ra,Pa,Pa,Si,La,Lu,La,De,De,Ra,De,La,La,Pa,Cu,Lu,Pa,Ra,Pa,Pa,Cu,Zi,Gu,Cu,Gu,La,Si,Ra,Pa",
}
# ROI table:
minimal_roi = {
"0": 0.574,
"1757": 0.158,
"3804": 0.089,
"6585": 0
}
# Stoploss:
stoploss = -0.28
# #################### END OF RESULT PLACE ####################
# 𝖂𝖔𝖗𝖘𝖙, 𝖀𝖓𝖎𝖉𝖊𝖆𝖑, 𝕾𝖚𝖇𝖔𝖕𝖙𝖎𝖒𝖆𝖑, 𝕸𝖆𝖑𝖆𝖕𝖗𝖔𝖕𝖔𝖘 𝕬𝖓𝖉 𝕯𝖎𝖘𝖒𝖆𝖑 𝖙𝖎𝖒𝖊𝖋𝖗𝖆𝖒𝖊 𝖋𝖔𝖗 𝖙𝖍𝖎𝖘 𝖘𝖙𝖗𝖆𝖙𝖊𝖌𝖞:
timeframe = '4h'
spell_pot = [
",".join(
tuple(
random.choices(
list(SPELLS.keys()),
# TODO: k will be change to len(pairlist)
k=PAIR_LIST_LENGHT
)
)
)for i in range(PAIN_RANGE)
]
buy_spell = CategoricalParameter(
spell_pot, default=spell_pot[0], space='buy')
sell_spell = CategoricalParameter(
spell_pot, default=spell_pot[0], space='sell')
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
pairs = self.dp.current_whitelist()
pairs_len = len(pairs)
pair_index = pairs.index(metadata['pair'])
buy_spells = self.buy_spell.value.split(",")
buy_spells_len = len(buy_spells)
if pairs_len > buy_spells_len:
print(
f"First set PAIR_LIST_LENGHT={pairs_len + 1} And re-hyperopt the")
print("Buy strategy And paste result in exact place(lines 535~564)")
print("IMPORTANT: You Need An 'STATIC' Pairlist On Your Config.json !!!")
exit()
buy_params_index = buy_spells[pair_index]
params = spell_finder(buy_params_index, 'buy')
conditions = list()
# TODO: Its not dry code!
buy_indicator = params['buy_indicator0']
buy_crossed_indicator = params['buy_crossed_indicator0']
buy_operator = params['buy_operator0']
buy_real_num = params['buy_real_num0']
condition, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition)
# backup
buy_indicator = params['buy_indicator1']
buy_crossed_indicator = params['buy_crossed_indicator1']
buy_operator = params['buy_operator1']
buy_real_num = params['buy_real_num1']
condition, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition)
buy_indicator = params['buy_indicator2']
buy_crossed_indicator = params['buy_crossed_indicator2']
buy_operator = params['buy_operator2']
buy_real_num = params['buy_real_num2']
condition, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition)
if conditions:
dataframe.loc[
reduce(lambda x, y: x & y, conditions),
'buy']=1
# print(len(dataframe.keys()))
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
return dataframe

155
Diamond.py Normal file
View File

@@ -0,0 +1,155 @@
# 𝐼𝓉 𝒾𝓈 𝒟𝒾𝒶𝓂𝑜𝓃𝒹 𝒮𝓉𝓇𝒶𝓉𝑒𝑔𝓎.
# 𝒯𝒽𝒶𝓉 𝓉𝒶𝓀𝑒𝓈 𝒽𝑒𝓇 𝑜𝓌𝓃 𝓇𝒾𝑔𝒽𝓉𝓈 𝓁𝒾𝓀𝑒 𝒜𝒻𝑔𝒽𝒶𝓃𝒾𝓈𝓉𝒶𝓃 𝓌𝑜𝓂𝑒𝓃
# 𝒯𝒽𝑜𝓈𝑒 𝓌𝒽𝑜 𝓈𝓉𝒾𝓁𝓁 𝓅𝓇𝑜𝓊𝒹 𝒶𝓃𝒹 𝒽𝑜𝓅𝑒𝒻𝓊𝓁.
# 𝒯𝒽𝑜𝓈𝑒 𝓌𝒽𝑜 𝓉𝒽𝑒 𝓂𝑜𝓈𝓉 𝒷𝑒𝒶𝓊𝓉𝒾𝒻𝓊𝓁 𝒸𝓇𝑒𝒶𝓉𝓊𝓇𝑒𝓈 𝒾𝓃 𝓉𝒽𝑒 𝒹𝑒𝓅𝓉𝒽𝓈 𝑜𝒻 𝓉𝒽𝑒 𝒹𝒶𝓇𝓀𝑒𝓈𝓉.
# 𝒯𝒽𝑜𝓈𝑒 𝓌𝒽𝑜 𝓈𝒽𝒾𝓃𝑒 𝓁𝒾𝓀𝑒 𝒹𝒾𝒶𝓂𝑜𝓃𝒹𝓈 𝒷𝓊𝓇𝒾𝑒𝒹 𝒾𝓃 𝓉𝒽𝑒 𝒽𝑒𝒶𝓇𝓉 𝑜𝒻 𝓉𝒽𝑒 𝒹𝑒𝓈𝑒𝓇𝓉 ...
# 𝒲𝒽𝓎 𝓃𝑜𝓉 𝒽𝑒𝓁𝓅 𝓌𝒽𝑒𝓃 𝓌𝑒 𝒸𝒶𝓃?
# 𝐼𝒻 𝓌𝑒 𝒷𝑒𝓁𝒾𝑒𝓋𝑒 𝓉𝒽𝑒𝓇𝑒 𝒾𝓈 𝓃𝑜 𝓂𝒶𝓃 𝓁𝑒𝒻𝓉 𝓌𝒾𝓉𝒽 𝓉𝒽𝑒𝓂
# (𝒲𝒽𝒾𝒸𝒽 𝒾𝓈 𝓅𝓇𝑜𝒷𝒶𝒷𝓁𝓎 𝓉𝒽𝑒 𝓅𝓇𝑜𝒹𝓊𝒸𝓉 𝑜𝒻 𝓉𝒽𝑒 𝓉𝒽𝑜𝓊𝑔𝒽𝓉 𝑜𝒻 𝓅𝒶𝒾𝓃𝓁𝑒𝓈𝓈 𝒸𝑜𝓇𝓅𝓈𝑒𝓈)
# 𝒲𝒽𝑒𝓇𝑒 𝒽𝒶𝓈 𝑜𝓊𝓇 𝒽𝓊𝓂𝒶𝓃𝒾𝓉𝓎 𝑔𝑜𝓃𝑒?
# 𝒲𝒽𝑒𝓇𝑒 𝒽𝒶𝓈 𝒽𝓊𝓂𝒶𝓃𝒾𝓉𝓎 𝑔𝑜𝓃𝑒?
# 𝒲𝒽𝓎 𝓃𝑜𝓉 𝒽𝑒𝓁𝓅 𝓌𝒽𝑒𝓃 𝓌𝑒 𝒸𝒶𝓃?
# 𝓁𝑒𝓉𝓈 𝓅𝒾𝓅 𝓊𝓃𝒾𝓃𝓈𝓉𝒶𝓁𝓁 𝓉𝒶-𝓁𝒾𝒷 𝑜𝓃 𝒜𝒻𝑔𝒽𝒶𝓃𝒾𝓈𝓉𝒶𝓃
# IMPORTANT: Diamond strategy is designed to be pure and
# cuz of that it have not any indicator population. idea is that
# It is just use the pure dataframe ohlcv data for calculation
# of buy/sell signals, But you can add your indicators and add
# your key names inside catagorical hyperoptable params and
# than you be able to hyperopt them as well.
# thanks to: @Kroissan, @drakes00 And @xmatthias for his patience and helps
# Author: @Mablue (Masoud Azizi)
# github: https://github.com/mablue/
# * freqtrade backtesting --strategy Diamond
# freqtrade hyperopt --hyperopt-loss ShortTradeDurHyperOptLoss --spaces buy sell roi trailing stoploss --strategy Diamond -j 2 -e 10
# * 3/10: 76 trades. 51/18/7 Wins/Draws/Losses. Avg profit 1.92%. Median profit 2.40%. Total profit 0.04808472 BTC ( 48.08%). Avg duration 5:06:00 min. Objective: 1.75299
# freqtrade hyperopt --hyperopt-loss OnlyProfitHyperOptLoss --spaces buy sell roi trailing stoploss --strategy Diamond -j 2 -e 10
# * 10/10: 76 trades. 39/34/3 Wins/Draws/Losses. Avg profit 0.61%. Median profit 0.05%. Total profit 0.01528359 BTC ( 15.28%). Avg duration 17:32:00 min. Objective: -0.01528
# freqtrade hyperopt --hyperopt-loss SharpeHyperOptLoss --spaces buy sell roi trailing stoploss --strategy Diamond -j 2 -e 10
# * 4/10: 15 trades. 10/2/3 Wins/Draws/Losses. Avg profit 1.52%. Median profit 7.99%. Total profit 0.00754274 BTC ( 7.54%). Avg duration 1 day, 0:04:00 min. Objective: -0.90653
# freqtrade hyperopt --hyperopt-loss SharpeHyperOptLossDaily --spaces buy sell roi trailing stoploss --strategy Diamond -j 2 -e 10
# * 7/10: 130 trades. 68/54/8 Wins/Draws/Losses. Avg profit 0.71%. Median profit 0.06%. Total profit 0.03050369 BTC ( 30.50%). Avg duration 10:07:00 min. Objective: -11.08185
# freqtrade hyperopt --hyperopt-loss SortinoHyperOptLoss --spaces buy sell roi trailing stoploss --strategy Diamond -j 2 -e 10
# * 2/10: 10 trades. 7/0/3 Wins/Draws/Losses. Avg profit 5.50%. Median profit 7.05%. Total profit 0.01817970 BTC ( 18.18%). Avg duration 0:27:00 min. Objective: -11.72450
# freqtrade hyperopt --hyperopt-loss SortinoHyperOptLossDaily --spaces buy sell roi trailing stoploss --strategy Diamond -j 2 -e 10
# | * Best | 3/10 | 165 | 98 63 4 | 1.00% | 0.05453885 BTC (54.54%) | 0 days 08:02:00 | 0.00442974 BTC (13.41%) | -41.371 |
# | * Best | 7/10 | 101 | 56 42 3 | 0.73% | 0.02444518 BTC (24.45%) | 0 days 13:08:00 | 0.00107122 BTC (3.24%) | -66.7687 |
# * 7/10: 101 trades. 56/42/3 Wins/Draws/Losses. Avg profit 0.73%. Median profit 0.13%. Total profit 0.02444518 BTC ( 24.45%). Avg duration 13:08:00 min. Objective: -66.76866
# freqtrade hyperopt --hyperopt-loss OnlyProfitHyperOptLoss --spaces buy sell roi trailing stoploss --strategy Diamond -j 2 -e 10
# * 7/10: 117 trades. 74/41/2 Wins/Draws/Losses. Avg profit 1.91%. Median profit 1.50%. Total profit 0.07370921 BTC ( 73.71%). Avg duration 9:26:00 min. Objective: -0.07371
# --- Do not remove these libs ---
from freqtrade.strategy.parameters import CategoricalParameter, DecimalParameter, IntParameter
from freqtrade.strategy.interface import IStrategy
from pandas import DataFrame
# --------------------------------
# Add your lib to import here
import talib.abstract as ta
from functools import reduce
import freqtrade.vendor.qtpylib.indicators as qtpylib
class Diamond(IStrategy):
# ###################### RESULT PLACE ######################
# Config: 5 x UNLIMITED STOCK costume pair list,
# hyperopt : 5000 x SortinoHyperOptLossDaily,
# 34/5000: 297 trades. 136/156/5 Wins/Draws/Losses. Avg profit 0.49%. Median profit 0.00%. Total profit 45.84477237 USDT ( 33.96Σ%). Avg duration 11:54:00 min. Objective: -46.50379
# Buy hyperspace params:
buy_params = {
"buy_fast_key": "high",
"buy_horizontal_push": 7,
"buy_slow_key": "volume",
"buy_vertical_push": 0.942,
}
# Sell hyperspace params:
sell_params = {
"sell_fast_key": "high",
"sell_horizontal_push": 10,
"sell_slow_key": "low",
"sell_vertical_push": 1.184,
}
# ROI table:
minimal_roi = {
"0": 0.242,
"13": 0.044,
"51": 0.02,
"170": 0
}
# Stoploss:
stoploss = -0.271
# Trailing stop:
trailing_stop = True
trailing_stop_positive = 0.011
trailing_stop_positive_offset = 0.054
trailing_only_offset_is_reached = False
# timeframe
timeframe = '5m'
# #################### END OF RESULT PLACE ####################
buy_vertical_push = DecimalParameter(0.5, 1.5, decimals=3, default=1, space='buy')
buy_horizontal_push = IntParameter(0, 10, default=0, space='buy')
buy_fast_key = CategoricalParameter(['open', 'high', 'low', 'close', 'volume',
# you can not enable this lines befour you
# populate an indicator for them and set
# the same key name for it
# 'ma_fast', 'ma_slow', {...}
], default='ma_fast', space='buy')
buy_slow_key = CategoricalParameter(['open', 'high', 'low', 'close', 'volume',
# 'ma_fast', 'ma_slow', {...}
], default='ma_slow', space='buy')
sell_vertical_push = DecimalParameter(0.5, 1.5, decimals=3, default=1, space='sell')
sell_horizontal_push = IntParameter(0, 10, default=0, space='sell')
sell_fast_key = CategoricalParameter(['open', 'high', 'low', 'close', 'volume',
# 'ma_fast', 'ma_slow', {...}
], default='ma_fast', space='sell')
sell_slow_key = CategoricalParameter(['open', 'high', 'low', 'close', 'volume',
# 'ma_fast', 'ma_slow', {...}
], default='ma_slow', space='sell')
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# you can add new indicators and enable them inside
# hyperoptable categorical params on the top
# dataframe['ma_fast'] = ta.SMA(dataframe, timeperiod=9)
# dataframe['ma_slow'] = ta.SMA(dataframe, timeperiod=18)
# dataframe['{...}'] = ta.{...}(dataframe, timeperiod={...})
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = []
conditions.append(
qtpylib.crossed_above
(
dataframe[self.buy_fast_key.value].shift(self.buy_horizontal_push.value),
dataframe[self.buy_slow_key.value] * self.buy_vertical_push.value
)
)
if conditions:
dataframe.loc[
reduce(lambda x, y: x & y, conditions),
'buy']=1
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = []
conditions.append(
qtpylib.crossed_below
(
dataframe[self.sell_fast_key.value].shift(self.sell_horizontal_push.value),
dataframe[self.sell_slow_key.value] * self.sell_vertical_push.value
)
)
if conditions:
dataframe.loc[
reduce(lambda x, y: x & y, conditions),
'sell']=1
return dataframe

77
Diamond.txt Normal file
View File

@@ -0,0 +1,77 @@
Result for strategy Diamond
========================================================== BACKTESTING REPORT ==========================================================
| Pair | Buys | Avg Profit % | Cum Profit % | Tot Profit USDT | Tot Profit % | Avg Duration | Win Draw Loss Win% |
|-----------+--------+----------------+----------------+-------------------+----------------+----------------+-------------------------|
| CELR/USDT | 40 | 1.20 | 47.95 | 47.999 | 4.80 | 6:14:00 | 25 15 0 100 |
| ETH/USDT | 432 | 0.09 | 39.39 | 39.431 | 3.94 | 14:42:00 | 197 226 9 45.6 |
| ROSE/USDT | 60 | 0.64 | 38.12 | 38.154 | 3.82 | 7:32:00 | 29 31 0 100 |
| SAND/USDT | 14 | 1.41 | 19.70 | 19.717 | 1.97 | 3:29:00 | 11 3 0 100 |
| ADA/USDT | 7 | 0.86 | 5.99 | 6.000 | 0.60 | 9:27:00 | 3 4 0 100 |
| AVAX/USDT | 7 | 0.86 | 5.99 | 6.000 | 0.60 | 3:30:00 | 3 4 0 100 |
| XRP/USDT | 7 | 0.86 | 5.99 | 6.000 | 0.60 | 2:55:00 | 3 4 0 100 |
| SOL/USDT | 4 | 0.86 | 3.43 | 3.435 | 0.34 | 3:36:00 | 2 2 0 100 |
| IOTX/USDT | 78 | 0.03 | 2.58 | 2.582 | 0.26 | 8:35:00 | 37 39 2 47.4 |
| BNB/USDT | 7 | 0.32 | 2.26 | 2.262 | 0.23 | 6:11:00 | 2 5 0 100 |
| GALA/USDT | 0 | 0.00 | 0.00 | 0.000 | 0.00 | 0:00 | 0 0 0 0 |
| TRX/USDT | 2 | 0.00 | 0.00 | 0.000 | 0.00 | 12:42:00 | 0 2 0 0 |
| BTC/USDT | 0 | 0.00 | 0.00 | 0.000 | 0.00 | 0:00 | 0 0 0 0 |
| EGLD/USDT | 300 | -0.13 | -39.93 | -39.973 | -4.00 | 14:28:00 | 134 156 10 44.7 |
| ZEC/USDT | 277 | -0.25 | -69.80 | -69.865 | -6.99 | 15:57:00 | 137 130 10 49.5 |
| TOTAL | 1235 | 0.05 | 61.68 | 61.742 | 6.17 | 13:32:00 | 583 621 31 47.2 |
========================================================== BUY TAG STATS ===========================================================
| TAG | Buys | Avg Profit % | Cum Profit % | Tot Profit USDT | Tot Profit % | Avg Duration | Win Draw Loss Win% |
|-------+--------+----------------+----------------+-------------------+----------------+----------------+-------------------------|
| TOTAL | 1235 | 0.05 | 61.68 | 61.742 | 6.17 | 13:32:00 | 583 621 31 47.2 |
======================================================= SELL REASON STATS ========================================================
| Sell Reason | Sells | Win Draws Loss Win% | Avg Profit % | Cum Profit % | Tot Profit USDT | Tot Profit % |
|--------------------+---------+--------------------------+----------------+----------------+-------------------+----------------|
| roi | 1202 | 581 621 0 100 | 0.63 | 759.35 | 760.111 | 50.62 |
| trailing_stop_loss | 24 | 2 0 22 8.3 | -23.86 | -572.56 | -573.132 | -38.17 |
| sell_signal | 4 | 0 0 4 0 | -14.02 | -56.06 | -56.117 | -3.74 |
| force_sell | 3 | 0 0 3 0 | -4.85 | -14.56 | -14.574 | -0.97 |
| stop_loss | 2 | 0 0 2 0 | -27.25 | -54.49 | -54.546 | -3.63 |
======================================================== LEFT OPEN TRADES REPORT =========================================================
| Pair | Buys | Avg Profit % | Cum Profit % | Tot Profit USDT | Tot Profit % | Avg Duration | Win Draw Loss Win% |
|-----------+--------+----------------+----------------+-------------------+----------------+------------------+-------------------------|
| ZEC/USDT | 1 | -1.32 | -1.32 | -1.320 | -0.13 | 2:40:00 | 0 0 1 0 |
| EGLD/USDT | 1 | -3.25 | -3.25 | -3.251 | -0.33 | 1:20:00 | 0 0 1 0 |
| ETH/USDT | 1 | -9.99 | -9.99 | -10.003 | -1.00 | 4 days, 10:50:00 | 0 0 1 0 |
| TOTAL | 3 | -4.85 | -14.56 | -14.574 | -1.46 | 1 day, 12:57:00 | 0 0 3 0 |
=============== SUMMARY METRICS ================
| Metric | Value |
|------------------------+---------------------|
| Backtesting from | 2021-01-01 00:00:00 |
| Backtesting to | 2021-11-20 00:00:00 |
| Max open trades | 15 |
| | |
| Total/Daily Avg Trades | 1235 / 3.82 |
| Starting balance | 1000.000 USDT |
| Final balance | 1061.742 USDT |
| Absolute profit | 61.742 USDT |
| Total profit % | 6.17% |
| Trades per day | 3.82 |
| Avg. daily profit % | 0.02% |
| Avg. stake amount | 100.000 USDT |
| Total trade volume | 123500.000 USDT |
| | |
| Best Pair | CELR/USDT 47.95% |
| Worst Pair | ZEC/USDT -69.80% |
| Best trade | EGLD/USDT 9.32% |
| Worst trade | IOTX/USDT -27.25% |
| Best day | 18.000 USDT |
| Worst day | -55.225 USDT |
| Days win/draw/lose | 201 / 100 / 23 |
| Avg. Duration Winners | 2:30:00 |
| Avg. Duration Loser | 4 days, 7:03:00 |
| Rejected Buy signals | 0 |
| | |
| Min balance | 940.516 USDT |
| Max balance | 1218.619 USDT |
| Drawdown | 277.83% |
| Drawdown | 278.103 USDT |
| Drawdown high | 218.619 USDT |
| Drawdown low | -59.484 USDT |
| Drawdown Start | 2021-05-12 06:00:00 |
| Drawdown End | 2021-07-20 03:05:00 |
| Market change | 2716.79% |
================================================

123
Empty.py Normal file
View File

@@ -0,0 +1,123 @@
# pr#agma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
# isort: skip_file
# --- Do not remove these libs ---
from datetime import datetime
import numpy as np # noqa
import pandas as pd # noqa
from pandas import DataFrame
from freqtrade.strategy.interface import IStrategy
# --------------------------------
# Add your lib to import here
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib
# This class is a sample. Feel free to customize it.
class Empty(IStrategy):
# Strategy interface version - allow new iterations of the strategy interface.
# Check the documentation or the Sample strategy to get the latest version.
INTERFACE_VERSION = 2
# ROI table:
minimal_roi = {
#"0": 0.015
"0": 0.5
}
# Stoploss:
stoploss = -1
trailing_stop = True
trailing_stop_positive = 0.001
trailing_stop_positive_offset = 0.0175 #0.015
trailing_only_offset_is_reached = True
#max_open_trades = 3
# Optimal ticker interval for the strategy.
timeframe = '5m'
# Run "populate_indicators()" only for new candle.
process_only_new_candles = False
# These values can be overridden in the "ask_strategy" section in the config.
use_sell_signal = True
sell_profit_only = False
ignore_roi_if_buy_signal = False
# Number of candles the strategy requires before producing valid signals
startup_candle_count: int = 30
plot_config = {
# Main plot indicators (Moving averages, ...)
'main_plot': {
'bb_lowerband': {'color': 'white'},
'bb_upperband': {'color': 'white'},
},
'subplots': {
# Subplots - each dict defines one additional plot
"BB": {
'bb_width': {'color': 'white'},
},
"Aaron": {
'aroonup': {'color': 'blue'},
'aroondown': {'color': 'red'}
}
}
}
def informative_pairs(self):
return []
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# MACD
#macd = ta.MACD(dataframe)
#dataframe['macd'] = macd['macd']
#dataframe['macdsignal'] = macd['macdsignal']
#dataframe['macdhist'] = macd['macdhist']
# RSI
#dataframe['rsi'] = ta.RSI(dataframe)
# 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"]
)
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[
(
# (
# (dataframe['close'] < dataframe['bb_lowerband'])
# & (dataframe['bb_width'] >= 0.065)
# #& (dataframe['rsi'] < 45)
# & (dataframe['volume'] > 0)
# )
),
'buy'] = 1
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[
(
),
'sell'] = 1
return dataframe

20
EnCirculation.txt Normal file
View File

@@ -0,0 +1,20 @@
132,670,764,300 DOGE
19,215,937 BTC
71,683,856 LTC
138,063,286 ETC
18,204,913 XMR
19,238,231 BCH
15,772,013 ZEC
50,298,735,565 XRP
34,424,965,305 ADA
8,734,317,475 MATIC
1,139,368,061 DOT
362,910,497 SOL
549,063,278,876,302 SHIB
92,159,192,741 TRX
300,677,692 AVAX
18,204,913 XMR
1,344,947,069 STX
13,572,466,120 ZIL
https://coinmarketcap.com/

328
FractalAtr.py Normal file
View File

@@ -0,0 +1,328 @@
# pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
# flake8: noqa: F401
# isort: skip_file
# --- Do not remove these libs ---
import logging
import numpy as np
import pandas as pd
from pandas import DataFrame
from datetime import datetime, timedelta
from typing import Optional, Union, Tuple
from freqtrade.exchange import timeframe_to_prev_date
from freqtrade.persistence import Trade
from freqtrade.strategy import (BooleanParameter, CategoricalParameter, DecimalParameter, stoploss_from_open,
IntParameter, IStrategy, merge_informative_pair, informative, stoploss_from_absolute)
# --------------------------------
# Add your lib to import here
import talib.abstract as ta
import pandas_ta as pta
from technical import qtpylib
class FractalAtr(IStrategy):
# Strategy interface version - allow new iterations of the strategy interface.
# Check the documentation or the Sample strategy to get the latest version.
INTERFACE_VERSION = 3
# Optimal timeframe for the strategy.
timeframe = '1m'
# Can this strategy go short?
can_short: bool = False
# Minimal ROI designed for the strategy.
# This attribute will be overridden if the config file contains "minimal_roi".
minimal_roi = {
"0": 0.5
}
# Optimal stoploss designed for the strategy.
# This attribute will be overridden if the config file contains "stoploss".
stoploss = -1
position_adjustment_enable = True
use_custom_stoploss = True
# Trailing stoploss
trailing_stop = False
# Run "populate_indicators()" only for new candle.
process_only_new_candles = True
# These values can be overridden in the config.
use_exit_signal = True
exit_profit_only = False
ignore_roi_if_entry_signal = False
# Number of candles the strategy requires before producing valid signals
startup_candle_count: int = 30
# Strategy parameters
buy_rsi = IntParameter(10, 40, default=30, space="buy")
sell_rsi = IntParameter(60, 90, default=70, space="sell")
# trailing stoploss hyperopt parameters
# hard stoploss profit
pHSL = DecimalParameter(-0.200, -0.040, default=-0.99, decimals=3, space='sell', optimize=False, load=True)
# profit threshold 1, trigger point, SL_1 is used
pPF_1 = DecimalParameter(0.008, 0.020, default=0.022, decimals=3, space='sell', optimize=True, load=True)
pSL_1 = DecimalParameter(0.008, 0.020, default=0.021, decimals=3, space='sell', optimize=True, load=True)
# profit threshold 2, SL_2 is used
pPF_2 = DecimalParameter(0.040, 0.100, default=0.080, decimals=3, space='sell', optimize=True, load=True)
pSL_2 = DecimalParameter(0.020, 0.070, default=0.040, decimals=3, space='sell', optimize=True, load=True)
# Optional order type mapping.
order_types = {
'entry': 'limit',
'exit': 'limit',
'stoploss': 'market',
'stoploss_on_exchange': False
}
# Optional order time in force.
order_time_in_force = {
'entry': 'GTC',
'exit': 'GTC'
}
locked_pairs = {}
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 True | (len(dataframe) < 1):
return None
last_candle = dataframe.iloc[-1].squeeze()
filled_buys = trade.select_filled_orders('buy')
count_of_buys = len(filled_buys)
condition = (last_candle['enter_long'] == 1) # & (last_candle['close'] <= last_candle['close_1h'])
# self.protection_nb_buy_lost.value
if (0 < count_of_buys <= 2) & (current_profit < - 0.1) & (condition):
try:
stake_amount = self.config['stake_amount']
print("Adjust " + trade.pair + " " + str(current_time) + " " + str(current_profit) + " " + str(count_of_buys) + " "
+ str(stake_amount))
return stake_amount
except Exception as exception:
print(exception)
return None
return None
def calculateScore(self, last_candle):
score = 1 #- (last_candle['percent10'] / 0.01
return score
@informative('1h')
def populate_indicators_1h(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
self.will_frac(dataframe)
dataframe['bear'] = dataframe['high'].where(dataframe['fractal_sup'] == True, 0)
dataframe['bear'] = dataframe['bear'].replace(to_replace=0, method="ffill")
dataframe['bull'] = dataframe['low'].where(dataframe['fractal_inf'] == True, 0)
dataframe['bull'] = dataframe['bull'].replace(to_replace=0, method="ffill")
dataframe['max72'] = ta.MAX(dataframe['close'], timeperiod=72)
dataframe['min72'] = ta.MIN(dataframe['close'], timeperiod=72)
dataframe['mid72'] = (dataframe['min72'] + (dataframe['max72'] - dataframe['min72']) / 2)
dataframe['width_72'] = (dataframe['max72'] - dataframe['min72']) / dataframe['max72']
dataframe['percent'] = dataframe['close'].pct_change()
dataframe['percent5'] = dataframe['close'].pct_change(5)
return dataframe
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
self.will_frac(dataframe)
dataframe['rsi'] = ta.RSI(dataframe)
dataframe['atr'] = ta.ATR(dataframe)
dataframe['bear'] = dataframe['high'].where(dataframe['fractal_sup'] == True, 0)
dataframe['bear'] = dataframe['bear'].replace(to_replace=0, method="ffill")
dataframe['bull'] = dataframe['low'].where(dataframe['fractal_inf'] == True, 0)
dataframe['bull'] = dataframe['bull'].replace(to_replace=0, method="ffill")
dataframe["percent"] = dataframe["close"].pct_change()
dataframe["percent3"] = dataframe["close"].pct_change(3)
dataframe["percent10"] = dataframe["close"].pct_change(10)
dataframe['min200'] = ta.MIN(dataframe['close'], timeperiod=200)
dataframe['max200'] = ta.MAX(dataframe['close'], timeperiod=200)
dataframe['atr_relatif'] = ta.ATR(dataframe) / dataframe["min200"]
dataframe["close50"] = dataframe["close"].rolling(50).mean()
dataframe["close3"] = dataframe["close"].rolling(3).mean()
dataframe['rsi_mean'] = dataframe['rsi'].rolling(3).mean()
dataframe['atr_relatif_mean'] = dataframe['atr_relatif'].rolling(3).mean()
dataframe['width_200'] = (dataframe['max200'] - dataframe['min200']) / dataframe['max200']
dataframe['width_close'] = (dataframe['close'] - dataframe['min200']) / dataframe['close']
dataframe['200_close'] = dataframe['width_close'] / dataframe['width_200'] * 100
dataframe['72h_close'] = (dataframe['close'] - dataframe['min72_1h']) / dataframe['min72_1h'] * 100
return dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[
(
(qtpylib.crossed_above(dataframe['close'], dataframe['bull']) |
qtpylib.crossed_above(dataframe['close'].shift(1), dataframe['bull'].shift(1)) |
qtpylib.crossed_above(dataframe['close'].shift(2), dataframe['bull'].shift(2))
) &
((dataframe['rsi'] < 20) | (dataframe['atr_relatif'] > 0.008)) &
# ((dataframe['200_close'] < 25) | (dataframe['width_200'] < 0.10)) &
(dataframe['close3'] < dataframe['close50']) & # Make sure Volume is not 0
(dataframe['volume'] > 0) # Make sure Volume is not 0
), ['buy', 'enter_tag']] = (1, 'buy_fractal')
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# dataframe.loc[
# (
# #(dataframe['volume'] > 0) # Make sure Volume is not 0
# ),
# 'exit_long'] = 1
return dataframe
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()
last_candle_12 = dataframe.iloc[-13].squeeze()
allow_to_buy = True #(not self.stop_all) #& (not self.all_down)
if pair in self.locked_pairs:
trade = self.locked_pairs[pair]
if (last_candle['close3'] >= last_candle['mid72_1h']):
print(pair + ' is locked ' + str(current_time) + " rate=" + str(rate) + " locked_rate=" + str(
trade.open_rate) + ' close3=' + str(last_candle['close3']) + ' mid72=' + str(last_candle['mid72_1h'])
+ str(trade))
allow_to_buy = False
# else:
# print(pair + ' unlocked ' + str(current_time) + " rate=" + str(rate) + " locked_rate=" + str(
# self.locked_pairs[pair]))
# del self.locked_pairs[pair]
if allow_to_buy:
print('Buy ' + entry_tag + ' ' + str(current_time) + ' ' + pair + " dispo=" + str(
round(self.wallets.get_available_stake_amount())) + " score=" + str(self.calculateScore(last_candle)))
return allow_to_buy
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()
string = ""
buy_signal = self.getTradeCandle(dataframe, trade)
if not buy_signal.empty:
buy_signal_candle = buy_signal.iloc[-1]
string = str(buy_signal_candle['date']) + ' open=' + str(buy_signal_candle['open']) \
+ " score=" + str(self.calculateScore(last_candle))
print('Sell trade ' + exit_reason + ' ' + str(current_time) + ' ' + pair + " dispo=" + str(
round(self.wallets.get_available_stake_amount())) #"+ str(amount) + ' ' + str(rate)
+ " open_rate=" + str(trade.open_rate) + " rate=" + str(rate) + " profit" + str(trade.calc_profit(rate, amount))
+ " " + string)
return True
def custom_exit(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
current_profit: float, **kwargs) -> 'Optional[Union[str, bool]]':
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
last_candle = dataframe.iloc[-1].squeeze()
if (last_candle['percent'] > 0) | (last_candle['percent3'] > -0.002):
return None
days = (current_time - trade.open_date_utc).days
hours = (current_time - trade.open_date_utc).seconds / 3600
minutes = (current_time - trade.open_date_utc).seconds / 60
# if (days >= 1) & (current_profit < -0.02):
# return 'too_old'
self.testLockedTrade(trade, current_profit, current_rate, current_time, pair)
# if pair in self.locked_pairs:
# print(pair + " stoploss")
# return "force_stoploss"
factor = 10
exit_atr = (trade.open_rate + (last_candle['atr'] * factor))
if (current_rate > exit_atr):
return "exit_atr"
def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
current_rate: float, current_profit: float, **kwargs) -> float:
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
last_candle = dataframe.iloc[-1].squeeze()
if (last_candle['percent'] > 0) | (last_candle['percent3'] > -0.002):
return -1
# print(pair + " " + str(current_time) + " rate=" + str(current_profit))
self.testLockedTrade(trade, current_profit, current_rate, current_time, pair)
# hard stoploss profit
HSL = self.pHSL.value
PF_1 = self.pPF_1.value
SL_1 = self.pSL_1.value
PF_2 = self.pPF_2.value
SL_2 = self.pSL_2.value
# For profits between PF_1 and PF_2 the stoploss (sl_profit) used is linearly interpolated
# between the values of SL_1 and SL_2. For all profits above PL_2 the sl_profit value
# rises linearly with current profit, for profits below PF_1 the hard stoploss profit is used.
if current_profit > PF_2:
sl_profit = SL_2 + (current_profit - PF_2)
elif (current_profit > PF_1):
sl_profit = SL_1 + ((current_profit - PF_1) * (SL_2 - SL_1) / (PF_2 - PF_1))
else:
sl_profit = HSL
return stoploss_from_open(sl_profit, current_profit)
# def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
# current_rate: float, current_profit: float, **kwargs) -> float:
# dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
# candle = dataframe.iloc[-1].squeeze()
# factor = 10
# return stoploss_from_absolute(current_rate - (candle['atr'] * factor), current_rate, is_short=trade.is_short)
def getTradeCandle(self, dataframe, trade: 'Trade'):
trade_open_date = timeframe_to_prev_date(self.timeframe, trade.open_date_utc)
buy_signal = dataframe.loc[dataframe['date'] <= trade_open_date]
return buy_signal
def testLockedTrade(self, trade: 'Trade', current_profit, current_rate, current_time, pair):
if current_profit <= -0.1:
if pair in self.locked_pairs:
trade = self.locked_pairs[pair]
if current_rate > trade.open_rate:
print(pair + ' unlocked ' + str(current_time) + " rate=" + str(current_rate) + " locked_rate=" + str(
trade.open_rate) + ' profit=' + str(current_profit))
del self.locked_pairs[pair]
# else:
# self.locked_pairs[pair] = current_rate
else:
self.locked_pairs[pair] = trade
# self.lock_pair(pair, until=current_time + timedelta(hours=24))
print(pair + " locked at " + str(current_time) + " rate=" + str(current_rate) + " locked_rate=" + str(
trade.open_rate) + ' profit=' + str(current_profit))
def will_frac(self, df: pd.DataFrame, period: int = 2) -> Tuple[pd.Series, pd.Series]:
"""
Indicate bearish and bullish fractal patterns using shifted Series.
:param df: OHLC data
:param period: number of lower (or higher) points on each side of a high (or low)
:return: tuple of boolean Series (bearish, bullish) where True marks a fractal pattern
"""
periods = [p for p in range(-period, period + 1) if p != 0] # default [-2, -1, 1, 2]
highs = [df['high'] > df['high'].shift(p) for p in periods]
bears = pd.Series(np.logical_and.reduce(highs), index=df.index)
lows = [df['low'] < df['low'].shift(p) for p in periods]
bulls = pd.Series(np.logical_and.reduce(lows), index=df.index)
df['fractal_sup'] = bears
df['fractal_inf'] = bulls
return df

433
FractalAtr2.py Normal file
View File

@@ -0,0 +1,433 @@
# pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
# flake8: noqa: F401
# isort: skip_file
# --- Do not remove these libs ---
import logging
import numpy as np
import pandas as pd
from pandas import DataFrame
from datetime import datetime, timedelta
from typing import Optional, Union, Tuple
from freqtrade.exchange import timeframe_to_prev_date
from freqtrade.persistence import Trade
from freqtrade.strategy import (BooleanParameter, CategoricalParameter, DecimalParameter, stoploss_from_open,
IntParameter, IStrategy, merge_informative_pair, informative, stoploss_from_absolute)
# --------------------------------
# Add your lib to import here
import talib.abstract as ta
import pandas_ta as pta
from technical import qtpylib
class FractalAtr2(IStrategy):
# Strategy interface version - allow new iterations of the strategy interface.
# Check the documentation or the Sample strategy to get the latest version.
INTERFACE_VERSION = 3
# Optimal timeframe for the strategy.
timeframe = '1m'
# Can this strategy go short?
can_short: bool = False
# Minimal ROI designed for the strategy.
# This attribute will be overridden if the config file contains "minimal_roi".
minimal_roi = {
"0": 0.5
}
# Optimal stoploss designed for the strategy.
# This attribute will be overridden if the config file contains "stoploss".
stoploss = -1
position_adjustment_enable = True
use_custom_stoploss = True
# Trailing stoploss
trailing_stop = False
# Run "populate_indicators()" only for new candle.
process_only_new_candles = True
# These values can be overridden in the config.
use_exit_signal = True
exit_profit_only = False
ignore_roi_if_entry_signal = False
# Number of candles the strategy requires before producing valid signals
startup_candle_count: int = 30
# Strategy parameters
buy_rsi = IntParameter(10, 40, default=30, space="buy")
sell_rsi = IntParameter(60, 90, default=70, space="sell")
# trailing stoploss hyperopt parameters
# hard stoploss profit
pHSL = DecimalParameter(-0.200, -0.040, default=-0.99, decimals=3, space='sell', optimize=False, load=True)
# profit threshold 1, trigger point, SL_1 is used
pPF_1 = DecimalParameter(0.008, 0.020, default=0.022, decimals=3, space='sell', optimize=True, load=True)
pSL_1 = DecimalParameter(0.008, 0.020, default=0.021, decimals=3, space='sell', optimize=True, load=True)
# profit threshold 2, SL_2 is used
pPF_2 = DecimalParameter(0.040, 0.100, default=0.080, decimals=3, space='sell', optimize=True, load=True)
pSL_2 = DecimalParameter(0.020, 0.070, default=0.040, decimals=3, space='sell', optimize=True, load=True)
# Optional order type mapping.
order_types = {
'entry': 'limit',
'exit': 'limit',
'stoploss': 'market',
'stoploss_on_exchange': False
}
# Optional order time in force.
order_time_in_force = {
'entry': 'GTC',
'exit': 'GTC'
}
locked_pairs = {}
max_profit_pairs = {}
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 True | (len(dataframe) < 1):
return None
last_candle = dataframe.iloc[-1].squeeze()
filled_buys = trade.select_filled_orders('buy')
count_of_buys = len(filled_buys)
condition = (last_candle['enter_long'] == 1) # & (last_candle['close'] <= last_candle['close_1h'])
# self.protection_nb_buy_lost.value
if (0 < count_of_buys <= 2) & (current_profit < - 0.1) & (condition):
try:
stake_amount = self.config['stake_amount']
print("Adjust " + trade.pair + " " + str(current_time) + " " + str(current_profit) + " " + str(count_of_buys) + " "
+ str(stake_amount))
return stake_amount
except Exception as exception:
print(exception)
return None
return None
def calculateScore(self, last_candle):
score = 1 #- (last_candle['percent10'] / 0.01
return score
@informative('1d')
def populate_indicators_1d(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe['rsi'] = ta.RSI(dataframe)
dataframe['atr'] = ta.ATR(dataframe)
dataframe['sma5'] = ta.SMA(dataframe, timeperiod=5)
# 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_ecart"] = ((dataframe["bb_upperband"] - dataframe["bb_lowerband"]))
dataframe["bb_width"] = (
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
)
return dataframe
@informative('1h')
def populate_indicators_1h(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
self.will_frac(dataframe)
dataframe['bear'] = dataframe['high'].where(dataframe['fractal_sup'] == True, 0)
dataframe['bear'] = dataframe['bear'].replace(to_replace=0, method="ffill")
dataframe['bull'] = dataframe['low'].where(dataframe['fractal_inf'] == True, 0)
dataframe['bull'] = dataframe['bull'].replace(to_replace=0, method="ffill")
dataframe['max72'] = ta.MAX(dataframe['close'], timeperiod=72)
dataframe['min72'] = ta.MIN(dataframe['close'], timeperiod=72)
dataframe['mid72'] = (dataframe['min72'] + (dataframe['max72'] - dataframe['min72']) / 2)
dataframe['width_72'] = (dataframe['max72'] - dataframe['min72']) / dataframe['max72']
dataframe['percent'] = dataframe['close'].pct_change()
dataframe['percent5'] = dataframe['close'].pct_change(5)
return dataframe
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
self.will_frac(dataframe)
dataframe['rsi'] = ta.RSI(dataframe)
dataframe['atr'] = ta.ATR(dataframe)
dataframe['bear'] = dataframe['high'].where(dataframe['fractal_sup'] == True, 0)
dataframe['bear'] = dataframe['bear'].replace(to_replace=0, method="ffill")
dataframe['bull'] = dataframe['low'].where(dataframe['fractal_inf'] == True, 0)
dataframe['bull'] = dataframe['bull'].replace(to_replace=0, method="ffill")
dataframe["percent"] = dataframe["close"].pct_change()
dataframe["percent3"] = dataframe["close"].pct_change(3)
dataframe["percent10"] = dataframe["close"].pct_change(10)
dataframe["diff_close1"] = dataframe["close"] - dataframe["close"].shift(1)
dataframe["diff_close3"] = dataframe["close"] - dataframe["close"].shift(3)
dataframe["diff_close5"] = dataframe["close"] - dataframe["close"].shift(5)
dataframe["diff_close10"] = dataframe["close"] - dataframe["close"].shift(10)
dataframe['min50'] = ta.MIN(dataframe['close'], timeperiod=50)
dataframe['max50'] = ta.MAX(dataframe['close'], timeperiod=50)
dataframe['min200'] = ta.MIN(dataframe['close'], timeperiod=200)
dataframe['min200_3'] = dataframe['min200'].rolling(3).mean()
dataframe['max200'] = ta.MAX(dataframe['close'], timeperiod=200)
dataframe['atr_relatif'] = ta.ATR(dataframe) / dataframe["min200"]
dataframe["close50"] = dataframe["close"].rolling(50).mean()
dataframe["close3"] = dataframe["close"].rolling(3).mean()
dataframe['rsi_mean'] = dataframe['rsi'].rolling(3).mean()
dataframe['atr_relatif_mean'] = dataframe['atr_relatif'].rolling(3).mean()
dataframe['width_200'] = (dataframe['max200'] - dataframe['min200']) / dataframe['max200']
dataframe['width_close'] = (dataframe['close'] - dataframe['min200']) / dataframe['close']
dataframe['200_close'] = dataframe['width_close'] / dataframe['width_200'] * 100
dataframe['72h_close'] = (dataframe['close'] - dataframe['min72_1h']) / dataframe['min72_1h'] * 100
# 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_ecart"] = ((dataframe["bb_upperband"] - dataframe["bb_lowerband"]))
dataframe["bb_width"] = (
(dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
)
return dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[
(
(qtpylib.crossed_above(dataframe['close'], dataframe['bull']) |
qtpylib.crossed_above(dataframe['close'].shift(1), dataframe['bull'].shift(1)) |
qtpylib.crossed_above(dataframe['close'].shift(2), dataframe['bull'].shift(2)) |
(dataframe['low'] <= dataframe['min200']) |
(dataframe['low'] <= dataframe['bb_lowerband_1d'])
) &
# ((dataframe['rsi'] < 60) | (dataframe['atr_relatif'] > 0.008)) &
# ((dataframe['200_close'] < 25) | (dataframe['width_200'] < 0.10)) &
(dataframe['open'] < dataframe['bb_upperband_1d']) &
(dataframe['bb_width'] >= 0.015) &
(dataframe['width_close'] <= 0.015) &
(dataframe['open'] < dataframe['close3']) &
(dataframe['open'] < dataframe['close50']) &
(dataframe['fractal_inf_1h'] == 1) &
#((dataframe['fractal_inf_1h'] == 1) | (dataframe['low'] <= dataframe['bb_lowerband_1d'])) &
# (dataframe['percent10'] < -0.005) &
(dataframe['volume'] > 0) # Make sure Volume is not 0
), ['buy', 'enter_tag']] = (1, 'buy_fractal')
# dataframe.loc[
# (
# # ((dataframe['200_close'] < 25) | (dataframe['width_200'] < 0.10)) &
# # (dataframe['close3'] <= dataframe['width_200']) &
# (dataframe['min200'].shift(5) == dataframe['min200']) &
# (dataframe['min72_1h'] > dataframe['min200']) &
# (dataframe['width_200'] > 0.035) &
# (dataframe['width_close'] == 0) &
# (dataframe['volume'] > 0) # Make sure Volume is not 0
#
# ), ['buy', 'enter_tag']] = (1, 'buy_min72')
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[
(
((dataframe['200_close'].shift(3) > 95) | (dataframe['200_close'].shift(2) > 95)
| (dataframe['200_close'].shift(1) > 95) | (dataframe['200_close'] > 95)
| (dataframe['percent'] < -0.005)
# | (dataframe['high'] >= dataframe['max50'])
# | ((dataframe['percent3'] < 0) & (dataframe['close3'].shift(1) >= dataframe['close3']))
)
&
(dataframe['percent'] < 0) &
(dataframe['volume'] > 0) # Make sure Volume is not 0
),
'exit_long'] = 1
return dataframe
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()
last_candle_12 = dataframe.iloc[-13].squeeze()
allow_to_buy = True #(not self.stop_all) #& (not self.all_down)
if pair in self.locked_pairs:
trade = self.locked_pairs[pair]
if (last_candle['close3'] >= last_candle['mid72_1h']):
print(pair + ' is locked ' + str(current_time) + " rate=" + str(rate) + " locked_rate=" + str(
trade.open_rate) + ' close3=' + str(last_candle['close3']) + ' mid72=' + str(last_candle['mid72_1h'])
+ str(trade))
allow_to_buy = False
# else:
# print(pair + ' unlocked ' + str(current_time) + " rate=" + str(rate) + " locked_rate=" + str(
# self.locked_pairs[pair]))
# del self.locked_pairs[pair]
if allow_to_buy:
print('Buy ' + entry_tag + ' ' + str(current_time) + ' ' + pair + " dispo=" + str(
round(self.wallets.get_available_stake_amount())) + " score=" + str(self.calculateScore(last_candle)))
return allow_to_buy
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()
days = (current_time - trade.open_date_utc).days
hours = (current_time - trade.open_date_utc).seconds / 3600
minutes = (current_time - trade.open_date_utc).seconds / 60
allow_to_sell = False #(minutes > 30)
profit = trade.calc_profit(rate, amount)
if not (pair in self.max_profit_pairs):
self.max_profit_pairs[pair] = profit
self.max_profit_pairs[pair] = max(self.max_profit_pairs[pair], profit)
if (self.max_profit_pairs[pair] > 0.5):
allow_decrease = 0.2 * self.max_profit_pairs[pair]
print("Max profit=" + str(self.max_profit_pairs[pair]) + ' ' + str(profit) + ' ' + str(allow_decrease))
if self.max_profit_pairs[pair] - profit < allow_decrease:
allow_to_sell = False
else:
allow_to_sell = True
# if last_candle['percent'] <=
if (profit < - 1.5):
print("Stop loss profit=" + str(self.max_profit_pairs[pair]) + ' ' + str(profit))
allow_to_sell = True
string = ""
buy_signal = self.getTradeCandle(dataframe, trade)
if not buy_signal.empty:
buy_signal_candle = buy_signal.iloc[-1]
string = str(buy_signal_candle['date']) + ' open=' + str(buy_signal_candle['open']) \
+ " score=" + str(self.calculateScore(last_candle))
if allow_to_sell:
print('Sell trade ' + exit_reason + ' ' + str(current_time) + ' ' + pair + " dispo=" + str(
round(self.wallets.get_available_stake_amount())) #"+ str(amount) + ' ' + str(rate)
+ " open_rate=" + str(trade.open_rate) + " rate=" + str(rate) + " profit=" + str(trade.calc_profit(rate, amount))
+ " " + string)
del self.max_profit_pairs[pair]
else:
print('Cancel Sell trade ' + exit_reason + ' ' + str(current_time) + ' ' + pair)
return allow_to_sell
def custom_exit(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
current_profit: float, **kwargs) -> 'Optional[Union[str, bool]]':
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
last_candle = dataframe.iloc[-1].squeeze()
if (last_candle['percent'] > 0) | (last_candle['percent3'] > -0.002):
return None
days = (current_time - trade.open_date_utc).days
hours = (current_time - trade.open_date_utc).seconds / 3600
minutes = (current_time - trade.open_date_utc).seconds / 60
if not (pair in self.max_profit_pairs):
self.max_profit_pairs[pair] = current_profit
self.max_profit_pairs[pair] = max(self.max_profit_pairs[pair], current_profit)
if (hours >= 2) & (self.max_profit_pairs[pair] < 0.002) & (self.max_profit_pairs[pair] > - 0.002):
return "no_change"
# if (days >= 1) & (current_profit < -0.02):
# return 'too_old'
self.testLockedTrade(trade, current_profit, current_rate, current_time, pair)
# if pair in self.locked_pairs:
# print(pair + " stoploss")
# return "force_stoploss"
factor = 10
exit_atr = (trade.open_rate + (last_candle['atr'] * factor))
if (current_rate > exit_atr):
return "exit_atr"
def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
current_rate: float, current_profit: float, **kwargs) -> float:
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
last_candle = dataframe.iloc[-1].squeeze()
if (last_candle['percent'] > 0) | (last_candle['percent3'] > -0.002):
return -1
# print(pair + " " + str(current_time) + " rate=" + str(current_profit))
self.testLockedTrade(trade, current_profit, current_rate, current_time, pair)
# hard stoploss profit
HSL = self.pHSL.value
PF_1 = self.pPF_1.value
SL_1 = self.pSL_1.value
PF_2 = self.pPF_2.value
SL_2 = self.pSL_2.value
# For profits between PF_1 and PF_2 the stoploss (sl_profit) used is linearly interpolated
# between the values of SL_1 and SL_2. For all profits above PL_2 the sl_profit value
# rises linearly with current profit, for profits below PF_1 the hard stoploss profit is used.
if current_profit > PF_2:
sl_profit = SL_2 + (current_profit - PF_2)
elif (current_profit > PF_1):
sl_profit = SL_1 + ((current_profit - PF_1) * (SL_2 - SL_1) / (PF_2 - PF_1))
else:
sl_profit = HSL
return stoploss_from_open(sl_profit, current_profit)
# def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
# current_rate: float, current_profit: float, **kwargs) -> float:
# dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
# candle = dataframe.iloc[-1].squeeze()
# factor = 10
# return stoploss_from_absolute(current_rate - (candle['atr'] * factor), current_rate, is_short=trade.is_short)
def getTradeCandle(self, dataframe, trade: 'Trade'):
trade_open_date = timeframe_to_prev_date(self.timeframe, trade.open_date_utc)
buy_signal = dataframe.loc[dataframe['date'] <= trade_open_date]
return buy_signal
def testLockedTrade(self, trade: 'Trade', current_profit, current_rate, current_time, pair):
return ""
if current_profit <= -0.1:
if pair in self.locked_pairs:
trade = self.locked_pairs[pair]
if current_rate > trade.open_rate:
print(pair + ' unlocked ' + str(current_time) + " rate=" + str(current_rate) + " locked_rate=" + str(
trade.open_rate) + ' profit=' + str(current_profit))
del self.locked_pairs[pair]
# else:
# self.locked_pairs[pair] = current_rate
else:
self.locked_pairs[pair] = trade
# self.lock_pair(pair, until=current_time + timedelta(hours=24))
print(pair + " locked at " + str(current_time) + " rate=" + str(current_rate) + " locked_rate=" + str(
trade.open_rate) + ' profit=' + str(current_profit))
def will_frac(self, df: pd.DataFrame, period: int = 2) -> Tuple[pd.Series, pd.Series]:
"""
Indicate bearish and bullish fractal patterns using shifted Series.
:param df: OHLC data
:param period: number of lower (or higher) points on each side of a high (or low)
:return: tuple of boolean Series (bearish, bullish) where True marks a fractal pattern
"""
periods = [p for p in range(-period, period + 1) if p != 0] # default [-2, -1, 1, 2]
highs = [df['high'] > df['high'].shift(p) for p in periods]
bears = pd.Series(np.logical_and.reduce(highs), index=df.index)
lows = [df['low'] < df['low'].shift(p) for p in periods]
bulls = pd.Series(np.logical_and.reduce(lows), index=df.index)
df['fractal_sup'] = bears
df['fractal_inf'] = bulls
return df

362
Genetic.py Normal file
View File

@@ -0,0 +1,362 @@
from freqtrade.strategy.interface import IStrategy
from pandas import DataFrame
# --------------------------------
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib
import numpy as np # noqa
def activate(x):
return np.tanh(x) # tanh
params = {
'0-0-0-w': -0.53814,
'0-0-bias': -0.96407,
'1-0-0-w': -0.49249,
'10-0-0-w': 0.08845,
'11-0-0-w': -0.14317,
'12-0-0-w': 0.00923,
'13-0-0-w': 0.30464,
'14-0-0-w': -0.35835,
'15-0-0-w': -0.49712,
'16-0-0-w': 0.76135,
'17-0-0-w': -0.75257,
'18-0-0-w': -0.04622,
'19-0-0-w': 0.10012,
'2-0-0-w': -0.23534,
'20-0-0-w': -0.04553,
'21-0-0-w': -0.35334,
'22-0-0-w': 0.17952,
'23-0-0-w': 0.44446,
'24-0-0-w': -0.15875,
'25-0-0-w': 0.97565,
'26-0-0-w': -0.89948,
'27-0-0-w': 0.61777,
'28-0-0-w': -0.60204,
'29-0-0-w': -0.85229,
'3-0-0-w': 0.47262,
'30-0-0-w': -0.52791,
'31-0-0-w': 0.98494,
'4-0-0-w': -0.54942,
'5-0-0-w': 0.40523,
'6-0-0-w': 0.4723,
'7-0-0-w': 0.63297,
'8-0-0-w': 0.07159,
'9-0-0-w': -0.86791,
'adx-bias': -0.48719,
'ao-bias': -0.87518,
'aroonosc-bias': -0.56096,
'bb_percent-bias': -0.98703,
'bb_width-bias': -0.73742,
'cci-bias': 0.47039,
'end-0-w': -0.81658,
'end-bias': 0.74656,
'fastd-bias': -0.2793,
'fisher_rsi_norm-bias': -0.36065,
'kc_percent-bias': 0.76707,
'kc_width-bias': 0.5489,
'macd-bias': 0.55448,
'macdhist-bias': -0.83133,
'macdsignal-bias': 0.30828,
'mfi-bias': -0.13097,
'roc-bias': -0.78885,
'rsi-bias': 0.9856,
'sar-bias': 0.43812,
'sma10-bias': -0.39019,
'sma100-bias': 0.03558,
'sma21-bias': 0.07457,
'sma3-bias': 0.93633,
'sma5-bias': -0.93329,
'sma50-bias': -0.60637,
'tema10-bias': -0.45946,
'tema100-bias': 0.1662,
'tema21-bias': 0.68466,
'tema3-bias': 0.25368,
'tema5-bias': -0.88818,
'tema50-bias': 0.3019,
'uo-bias': 0.71019,
'wbb_percent-bias': -0.55964,
'wbb_width-bias': 0.23523,
's-0-0-0-w': 0.85409,
's-0-0-bias': -0.04613,
's-1-0-0-w': -0.14997,
's-10-0-0-w': -0.67008,
's-11-0-0-w': -0.40221,
's-12-0-0-w': 0.64553,
's-13-0-0-w': 0.22838,
's-14-0-0-w': 0.99977,
's-15-0-0-w': 0.89363,
's-16-0-0-w': -0.88212,
's-17-0-0-w': -0.71813,
's-18-0-0-w': 0.41602,
's-19-0-0-w': -0.48389,
's-2-0-0-w': 0.09649,
's-20-0-0-w': 0.64273,
's-21-0-0-w': -0.31671,
's-22-0-0-w': 0.9663,
's-23-0-0-w': 0.00229,
's-24-0-0-w': 0.96244,
's-25-0-0-w': -0.24513,
's-26-0-0-w': 0.52312,
's-27-0-0-w': 0.44742,
's-28-0-0-w': -0.03916,
's-29-0-0-w': 0.88882,
's-3-0-0-w': -0.32112,
's-30-0-0-w': -0.70886,
's-31-0-0-w': -0.42672,
's-4-0-0-w': -0.55265,
's-5-0-0-w': 0.56105,
's-6-0-0-w': 0.47436,
's-7-0-0-w': 0.58136,
's-8-0-0-w': -0.48308,
's-9-0-0-w': -0.16024,
's-adx-bias': -0.4091,
's-ao-bias': 0.76889,
's-aroonosc-bias': 0.16228,
's-bb_percent-bias': 0.19407,
's-bb_width-bias': 0.11795,
's-cci-bias': 0.8379,
's-end-0-w': -0.14648,
's-end-bias': -0.85697,
's-fastd-bias': -0.00581,
's-fisher_rsi_norm-bias': -0.05253,
's-kc_percent-bias': -0.3562,
's-kc_width-bias': 0.67451,
's-macd-bias': -0.17742,
's-macdhist-bias': -0.58328,
's-macdsignal-bias': -0.79847,
's-mfi-bias': -0.48236,
's-roc-bias': -0.5914,
's-rsi-bias': -0.9618,
's-sar-bias': 0.57033,
's-sma10-bias': 0.14349,
's-sma100-bias': 0.02401,
's-sma21-bias': 0.78191,
's-sma3-bias': 0.72279,
's-sma5-bias': -0.19383,
's-sma50-bias': 0.63697,
's-tema10-bias': 0.96837,
's-tema100-bias': 0.77171,
's-tema21-bias': 0.67279,
's-tema3-bias': -0.24583,
's-tema5-bias': -0.08997,
's-tema50-bias': 0.65532,
's-uo-bias': 0.67701,
's-wbb_percent-bias': -0.658,
's-wbb_width-bias': -0.71056
}
network_shape = [1]
class Genetic(IStrategy):
# ROI table:
minimal_roi = {
"0": 0.21029,
"11": 0.05876,
"57": 0.02191,
"281": 0
}
# Stoploss:
stoploss = -0.07693
# Optimal ticker interval for the strategy
ticker_interval = '2h'
# Trailing stop:
trailing_only_offset_is_reached = False
trailing_stop = True
trailing_stop_positive = 0.01019
trailing_stop_positive_offset = 0.01164
# run "populate_indicators" only for new candle
process_only_new_candles = True
# Experimental settings (configuration will overide these if set)
use_sell_signal = True
sell_profit_only = True
ignore_roi_if_buy_signal = True
startup_candle_count = 100
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Adds several different TA indicators to the given DataFrame
Performance Note: For the best performance be frugal on the number of indicators
you are using. Let uncomment only the indicator you are using in your strategies
or your hyperopt configuration, otherwise you will waste your memory and CPU usage.
"""
# Momentum Indicators
# ------------------------------------
# ADX
dataframe['adx'] = ta.ADX(dataframe) / 100
# # Plus Directional Indicator / Movement
# dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
# dataframe['plus_di'] = ta.PLUS_DI(dataframe)
# # Minus Directional Indicator / Movement
# dataframe['minus_dm'] = ta.MINUS_DM(dataframe)
# dataframe['minus_di'] = ta.MINUS_DI(dataframe)
# # Aroon, Aroon Oscillator
# aroon = ta.AROON(dataframe)
# dataframe['aroonup'] = aroon['aroonup']
# dataframe['aroondown'] = aroon['aroondown']
dataframe['aroonosc'] = ta.AROONOSC(dataframe) / 100
# # Awesome Oscillator
dataframe['ao'] = ((qtpylib.awesome_oscillator(dataframe) > 0).astype(int) - 0.5) * 2
# # Keltner Channel
keltner = qtpylib.keltner_channel(dataframe)
dataframe["kc_upperband"] = keltner["upper"]
dataframe["kc_lowerband"] = keltner["lower"]
dataframe["kc_middleband"] = keltner["mid"]
dataframe["kc_percent"] = (
(dataframe["close"] - dataframe["kc_lowerband"]) /
(dataframe["kc_upperband"] - dataframe["kc_lowerband"])
)
dataframe["kc_width"] = (
(dataframe["kc_upperband"] - dataframe["kc_lowerband"]) / dataframe["kc_middleband"]
)
# # Ultimate Oscillator
dataframe['uo'] = ta.ULTOSC(dataframe) / 100
# # Commodity Channel Index: values [Oversold:-100, Overbought:100]
dataframe['cci'] = ta.CCI(dataframe) / 200
# RSI
dataframe['rsi'] = ta.RSI(dataframe) / 100
# # Inverse Fisher transform on RSI: values [-1.0, 1.0] (https://goo.gl/2JGGoy)
rsi = 0.1 * (dataframe['rsi'] * 100 - 50)
fisher_rsi = (np.exp(2 * rsi) - 1) / (np.exp(2 * rsi) + 1)
# # Inverse Fisher transform on RSI normalized: values [0.0, 100.0] (https://goo.gl/2JGGoy)
dataframe['fisher_rsi_norm'] = 50 * (fisher_rsi + 1) / 100
# # Stochastic Slow
# stoch = ta.STOCH(dataframe)
# dataframe['slowd'] = stoch['slowd']
# dataframe['slowk'] = stoch['slowk']
# Stochastic Fast
stoch_fast = ta.STOCHF(dataframe)
dataframe['fastd'] = stoch_fast['fastd'] / 100
# # Stochastic RSI
# stoch_rsi = ta.STOCHRSI(dataframe)
# dataframe['fastd_rsi'] = stoch_rsi['fastd']
# dataframe['fastk_rsi'] = stoch_rsi['fastk']
# MACD
macd = ta.MACD(dataframe)
dataframe['macd'] = macd['macd']
dataframe['macdsignal'] = macd['macdsignal']
dataframe['macdhist'] = macd['macdhist']
# MFI
dataframe['mfi'] = ta.MFI(dataframe) / 100
# # ROC
dataframe['roc'] = ta.ROC(dataframe) / 100
# Overlap Studies
# ------------------------------------
# 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"]
)
# 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"]
)
# # SMA - Simple Moving Average
dataframe['sma3'] = dataframe['close'] / ta.SMA(dataframe, timeperiod=3) - 1
dataframe['sma5'] = dataframe['close'] / ta.SMA(dataframe, timeperiod=5) - 1
dataframe['sma10'] = dataframe['close'] / ta.SMA(dataframe, timeperiod=10) - 1
dataframe['sma21'] = dataframe['close'] / ta.SMA(dataframe, timeperiod=21) - 1
dataframe['sma50'] = dataframe['close'] / ta.SMA(dataframe, timeperiod=50) - 1
dataframe['sma100'] = dataframe['close'] / ta.SMA(dataframe, timeperiod=100) - 1
# Parabolic SAR
dataframe['sar'] = dataframe['close'] / ta.SAR(dataframe) - 1
# TEMA - Triple Exponential Moving Average
dataframe['tema3'] = dataframe['close'] / ta.TEMA(dataframe, timeperiod=3) - 1
dataframe['tema5'] = dataframe['close'] / ta.TEMA(dataframe, timeperiod=5) - 1
dataframe['tema10'] = dataframe['close'] / ta.TEMA(dataframe, timeperiod=10) - 1
dataframe['tema21'] = dataframe['close'] / ta.TEMA(dataframe, timeperiod=21) - 1
dataframe['tema50'] = dataframe['close'] / ta.TEMA(dataframe, timeperiod=50) - 1
dataframe['tema100'] = dataframe['close'] / ta.TEMA(dataframe, timeperiod=100) - 1
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Based on TA indicators, populates the buy signal for the given dataframe
:param dataframe: DataFrame
:return: DataFrame with buy column
"""
indicators = ['aroonosc', 'ao', 'uo', 'cci', 'rsi', 'fisher_rsi_norm', 'sar',
'sma3', 'sma5', 'sma10', 'sma21', 'sma50', 'sma100',
'tema3', 'tema5', 'tema10', 'tema21', 'tema50', 'tema100',
'fastd', 'adx', 'bb_percent', 'bb_width', 'macd', 'macdsignal', 'macdhist', 'mfi',
'wbb_percent', 'wbb_width', 'roc', 'kc_percent', 'kc_width']
inputs = []
for indicator in indicators:
inputs.append(dataframe[indicator] + params[indicator + '-bias'])
for index, layer_size in enumerate(network_shape):
outputs = []
for n in range(layer_size):
weight = 0
for i, input in enumerate(inputs):
weight += params['{}-{}-{}-w'.format(i, index, n)] * input
weight += params['{}-{}-bias'.format(index, n)]
outputs.append(activate(weight))
inputs = outputs
weight = 0
for i, input in enumerate(inputs):
weight += params['end-{}-w'.format(i)] * input
weight += params['end-bias']
dataframe.loc[activate(weight) > 0, 'buy'] = 1
# Check that the candle had volume
dataframe.loc[dataframe['volume'] <= 0, 'buy'] = 0
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
return dataframe

171
GodStra.py Normal file
View File

@@ -0,0 +1,171 @@
# GodStra Strategy
# Author: @Mablue (Masoud Azizi)
# github: https://github.com/mablue/
# IMPORTANT:Add to your pairlists inside config.json (Under StaticPairList):
# {
# "method": "AgeFilter",
# "min_days_listed": 30
# },
# IMPORTANT: INSTALL TA BEFOUR RUN(pip install ta)
# IMPORTANT: Use Smallest "max_open_trades" for getting best results inside config.json
# --- Do not remove these libs ---
from freqtrade.strategy.interface import IStrategy
from pandas import DataFrame
# --------------------------------
# Add your lib to import here
# import talib.abstract as ta
from ta import add_all_ta_features
from ta.utils import dropna
import freqtrade.vendor.qtpylib.indicators as qtpylib
from functools import reduce
import numpy as np
class GodStra(IStrategy):
# 5/66: 9 trades. 8/0/1 Wins/Draws/Losses. Avg profit 21.83%. Median profit 35.52%. Total profit 1060.11476586 USDT ( 196.50Σ%). Avg duration 3440.0 min. Objective: -7.06960
# +--------+---------+----------+------------------+--------------+-------------------------------+----------------+-------------+
# | Best | Epoch | Trades | Win Draw Loss | Avg profit | Profit | Avg duration | Objective |
# |--------+---------+----------+------------------+--------------+-------------------------------+----------------+-------------|
# | * Best | 1/500 | 11 | 2 1 8 | 5.22% | 280.74230393 USDT (57.40%) | 2,421.8 m | -2.85206 |
# | * Best | 2/500 | 10 | 7 0 3 | 18.76% | 983.46414442 USDT (187.58%) | 360.0 m | -4.32665 |
# | * Best | 5/500 | 9 | 8 0 1 | 21.83% | 1,060.11476586 USDT (196.50%) | 3,440.0 m | -7.0696 |
# Buy hyperspace params:
buy_params = {
'buy-cross-0': 'volatility_kcc',
'buy-indicator-0': 'trend_ichimoku_base',
'buy-int-0': 42,
'buy-oper-0': '<R',
'buy-real-0': 0.06295
}
# Sell hyperspace params:
sell_params = {
'sell-cross-0': 'volume_mfi',
'sell-indicator-0': 'trend_kst_diff',
'sell-int-0': 98,
'sell-oper-0': '=R',
'sell-real-0': 0.8779
}
# ROI table:
minimal_roi = {
"0": 0.3556,
"4818": 0.21275,
"6395": 0.09024,
"22372": 0
}
# Stoploss:
stoploss = -0.34549
# Trailing stop:
trailing_stop = True
trailing_stop_positive = 0.22673
trailing_stop_positive_offset = 0.2684
trailing_only_offset_is_reached = True
# Buy hypers
timeframe = '12h'
print('Add {\n\t"method": "AgeFilter",\n\t"min_days_listed": 30\n},\n to your pairlists in config (Under StaticPairList)')
def dna_size(self, dct: dict):
def int_from_str(st: str):
str_int = ''.join([d for d in st if d.isdigit()])
if str_int:
return int(str_int)
return -1 # in case if the parameter somehow doesn't have index
return len({int_from_str(digit) for digit in dct.keys()})
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# Add all ta features
dataframe = dropna(dataframe)
dataframe = add_all_ta_features(
dataframe, open="open", high="high", low="low", close="close", volume="volume",
fillna=True)
# dataframe.to_csv("df.csv", index=True)
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = list()
# /5: Cuz We have 5 Group of variables inside buy_param
for i in range(self.dna_size(self.buy_params)):
OPR = self.buy_params[f'buy-oper-{i}']
IND = self.buy_params[f'buy-indicator-{i}']
CRS = self.buy_params[f'buy-cross-{i}']
INT = self.buy_params[f'buy-int-{i}']
REAL = self.buy_params[f'buy-real-{i}']
DFIND = dataframe[IND]
DFCRS = dataframe[CRS]
if OPR == ">":
conditions.append(DFIND > DFCRS)
elif OPR == "=":
conditions.append(np.isclose(DFIND, DFCRS))
elif OPR == "<":
conditions.append(DFIND < DFCRS)
elif OPR == "CA":
conditions.append(qtpylib.crossed_above(DFIND, DFCRS))
elif OPR == "CB":
conditions.append(qtpylib.crossed_below(DFIND, DFCRS))
elif OPR == ">I":
conditions.append(DFIND > INT)
elif OPR == "=I":
conditions.append(DFIND == INT)
elif OPR == "<I":
conditions.append(DFIND < INT)
elif OPR == ">R":
conditions.append(DFIND > REAL)
elif OPR == "=R":
conditions.append(np.isclose(DFIND, REAL))
elif OPR == "<R":
conditions.append(DFIND < REAL)
#print(conditions)
dataframe.loc[
reduce(lambda x, y: x & y, conditions),
'buy'] = 1
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = list()
for i in range(self.dna_size(self.sell_params)):
OPR = self.sell_params[f'sell-oper-{i}']
IND = self.sell_params[f'sell-indicator-{i}']
CRS = self.sell_params[f'sell-cross-{i}']
INT = self.sell_params[f'sell-int-{i}']
REAL = self.sell_params[f'sell-real-{i}']
DFIND = dataframe[IND]
DFCRS = dataframe[CRS]
if OPR == ">":
conditions.append(DFIND > DFCRS)
elif OPR == "=":
conditions.append(np.isclose(DFIND, DFCRS))
elif OPR == "<":
conditions.append(DFIND < DFCRS)
elif OPR == "CA":
conditions.append(qtpylib.crossed_above(DFIND, DFCRS))
elif OPR == "CB":
conditions.append(qtpylib.crossed_below(DFIND, DFCRS))
elif OPR == ">I":
conditions.append(DFIND > INT)
elif OPR == "=I":
conditions.append(DFIND == INT)
elif OPR == "<I":
conditions.append(DFIND < INT)
elif OPR == ">R":
conditions.append(DFIND > REAL)
elif OPR == "=R":
conditions.append(np.isclose(DFIND, REAL))
elif OPR == "<R":
conditions.append(DFIND < REAL)
dataframe.loc[
reduce(lambda x, y: x & y, conditions),
'sell'] = 1
return dataframe

73
GodStra.txt Normal file
View File

@@ -0,0 +1,73 @@
Result for strategy GodStra
============================================================ BACKTESTING REPORT ===========================================================
| Pair | Buys | Avg Profit % | Cum Profit % | Tot Profit USDT | Tot Profit % | Avg Duration | Win Draw Loss Win% |
|-----------+--------+----------------+----------------+-------------------+----------------+-------------------+-------------------------|
| CELR/USDT | 29 | 22.26 | 645.61 | 646.251 | 64.63 | 7 days, 22:45:00 | 23 0 6 79.3 |
| IOTX/USDT | 22 | 22.29 | 490.44 | 490.932 | 49.09 | 11 days, 4:16:00 | 17 0 5 77.3 |
| TRX/USDT | 10 | 15.73 | 157.35 | 157.504 | 15.75 | 12 days, 15:54:00 | 9 1 0 100 |
| ROSE/USDT | 8 | 15.41 | 123.24 | 123.365 | 12.34 | 8 days, 6:48:00 | 8 0 0 100 |
| SAND/USDT | 2 | 51.72 | 103.45 | 103.552 | 10.36 | 10 days, 3:55:00 | 2 0 0 100 |
| GALA/USDT | 2 | 0.42 | 0.84 | 0.846 | 0.08 | 1 day, 11:50:00 | 1 0 1 50.0 |
| ZEC/USDT | 0 | 0.00 | 0.00 | 0.000 | 0.00 | 0:00 | 0 0 0 0 |
| ADA/USDT | 0 | 0.00 | 0.00 | 0.000 | 0.00 | 0:00 | 0 0 0 0 |
| AVAX/USDT | 0 | 0.00 | 0.00 | 0.000 | 0.00 | 0:00 | 0 0 0 0 |
| XRP/USDT | 0 | 0.00 | 0.00 | 0.000 | 0.00 | 0:00 | 0 0 0 0 |
| ETH/USDT | 0 | 0.00 | 0.00 | 0.000 | 0.00 | 0:00 | 0 0 0 0 |
| BNB/USDT | 0 | 0.00 | 0.00 | 0.000 | 0.00 | 0:00 | 0 0 0 0 |
| SOL/USDT | 0 | 0.00 | 0.00 | 0.000 | 0.00 | 0:00 | 0 0 0 0 |
| EGLD/USDT | 0 | 0.00 | 0.00 | 0.000 | 0.00 | 0:00 | 0 0 0 0 |
| BTC/USDT | 0 | 0.00 | 0.00 | 0.000 | 0.00 | 0:00 | 0 0 0 0 |
| TOTAL | 73 | 20.83 | 1520.93 | 1522.449 | 152.24 | 9 days, 11:42:00 | 60 1 12 82.2 |
=========================================================== BUY TAG STATS ============================================================
| TAG | Buys | Avg Profit % | Cum Profit % | Tot Profit USDT | Tot Profit % | Avg Duration | Win Draw Loss Win% |
|-------+--------+----------------+----------------+-------------------+----------------+------------------+-------------------------|
| TOTAL | 73 | 20.83 | 1520.93 | 1522.449 | 152.24 | 9 days, 11:42:00 | 60 1 12 82.2 |
======================================================= SELL REASON STATS ========================================================
| Sell Reason | Sells | Win Draws Loss Win% | Avg Profit % | Cum Profit % | Tot Profit USDT | Tot Profit % |
|--------------------+---------+--------------------------+----------------+----------------+-------------------+----------------|
| trailing_stop_loss | 32 | 32 0 0 100 | 40.32 | 1290.39 | 1291.68 | 86.03 |
| roi | 29 | 28 1 0 100 | 22.3 | 646.69 | 647.341 | 43.11 |
| stop_loss | 12 | 0 0 12 0 | -34.68 | -416.16 | -416.573 | -27.74 |
====================================================== LEFT OPEN TRADES REPORT ======================================================
| Pair | Buys | Avg Profit % | Cum Profit % | Tot Profit USDT | Tot Profit % | Avg Duration | Win Draw Loss Win% |
|--------+--------+----------------+----------------+-------------------+----------------+----------------+-------------------------|
| TOTAL | 0 | 0.00 | 0.00 | 0.000 | 0.00 | 0:00 | 0 0 0 0 |
=============== SUMMARY METRICS ================
| Metric | Value |
|------------------------+---------------------|
| Backtesting from | 2021-01-01 00:00:00 |
| Backtesting to | 2021-11-20 00:00:00 |
| Max open trades | 15 |
| | |
| Total/Daily Avg Trades | 73 / 0.23 |
| Starting balance | 1000.000 USDT |
| Final balance | 2522.449 USDT |
| Absolute profit | 1522.449 USDT |
| Total profit % | 152.24% |
| Trades per day | 0.23 |
| Avg. daily profit % | 0.47% |
| Avg. stake amount | 100.000 USDT |
| Total trade volume | 7300.000 USDT |
| | |
| Best Pair | CELR/USDT 645.61% |
| Worst Pair | ZEC/USDT 0.00% |
| Best trade | IOTX/USDT 164.23% |
| Worst trade | IOTX/USDT -34.68% |
| Best day | 164.398 USDT |
| Worst day | -69.429 USDT |
| Days win/draw/lose | 50 / 237 / 10 |
| Avg. Duration Winners | 9 days, 11:34:00 |
| Avg. Duration Loser | 8 days, 18:02:00 |
| Rejected Buy signals | 0 |
| | |
| Min balance | 1001.510 USDT |
| Max balance | 2522.449 USDT |
| Drawdown | 96.63% |
| Drawdown | 96.722 USDT |
| Drawdown high | 1155.213 USDT |
| Drawdown low | 1058.490 USDT |
| Drawdown Start | 2021-05-28 06:25:00 |
| Drawdown End | 2021-06-22 00:20:00 |
| Market change | 2716.79% |
================================================

200
GodStraHo.py Normal file
View File

@@ -0,0 +1,200 @@
# GodStra Strategy Hyperopt
# Author: @Mablue (Masoud Azizi)
# github: https://github.com/mablue/
# IMPORTANT: INSTALL TA BEFOUR RUN:
# :~$ pip install ta
# freqtrade hyperopt --hyperopt GodStraHo --hyperopt-loss SharpeHyperOptLossDaily --spaces all --strategy GodStra --config config.json -e 100
# --- Do not remove these libs ---
from functools import reduce
from typing import Any, Callable, Dict, List
import numpy as np # noqa
import pandas as pd # noqa
from pandas import DataFrame
from skopt.space import Categorical, Dimension, Integer, Real # noqa
from freqtrade.optimize.hyperopt_interface import IHyperOpt
# --------------------------------
# Add your lib to import here
# import talib.abstract as ta # noqa
import talib.abstract as ta
from ta import add_all_ta_features
from ta.utils import dropna
import freqtrade.vendor.qtpylib.indicators as qtpylib
# this is your trading strategy DNA Size
# you can change it and see the results...
DNA_SIZE = 1
GodGenes = ["open", "high", "low", "close", "volume", "volume_adi", "volume_obv",
"volume_cmf", "volume_fi", "volume_mfi", "volume_em", "volume_sma_em", "volume_vpt",
"volume_nvi", "volume_vwap", "volatility_atr", "volatility_bbm", "volatility_bbh",
"volatility_bbl", "volatility_bbw", "volatility_bbp", "volatility_bbhi",
"volatility_bbli", "volatility_kcc", "volatility_kch", "volatility_kcl",
"volatility_kcw", "volatility_kcp", "volatility_kchi", "volatility_kcli",
"volatility_dcl", "volatility_dch", "volatility_dcm", "volatility_dcw",
"volatility_dcp", "volatility_ui", "trend_macd", "trend_macd_signal",
"trend_macd_diff", "trend_sma_fast", "trend_sma_slow", "trend_ema_fast",
"trend_ema_slow", "trend_adx", "trend_adx_pos", "trend_adx_neg", "trend_vortex_ind_pos",
"trend_vortex_ind_neg", "trend_vortex_ind_diff", "trend_trix",
"trend_mass_index", "trend_cci", "trend_dpo", "trend_kst",
"trend_kst_sig", "trend_kst_diff", "trend_ichimoku_conv",
"trend_ichimoku_base", "trend_ichimoku_a", "trend_ichimoku_b",
"trend_visual_ichimoku_a", "trend_visual_ichimoku_b", "trend_aroon_up",
"trend_aroon_down", "trend_aroon_ind", "trend_psar_up", "trend_psar_down",
"trend_psar_up_indicator", "trend_psar_down_indicator", "trend_stc",
"momentum_rsi", "momentum_stoch_rsi", "momentum_stoch_rsi_k",
"momentum_stoch_rsi_d", "momentum_tsi", "momentum_uo", "momentum_stoch",
"momentum_stoch_signal", "momentum_wr", "momentum_ao", "momentum_kama",
"momentum_roc", "momentum_ppo", "momentum_ppo_signal", "momentum_ppo_hist",
"others_dr", "others_dlr", "others_cr"]
class GodStraHo(IHyperOpt):
@staticmethod
def indicator_space() -> List[Dimension]:
"""
Define your Hyperopt space for searching buy strategy parameters.
"""
gene = list()
for i in range(DNA_SIZE):
gene.append(Categorical(GodGenes, name=f'buy-indicator-{i}'))
gene.append(Categorical(GodGenes, name=f'buy-cross-{i}'))
gene.append(Integer(-1, 101, name=f'buy-int-{i}'))
gene.append(Real(-1.1, 1.1, name=f'buy-real-{i}'))
# Operations
# CA: Crossed Above, CB: Crossed Below,
# I: Integer, R: Real, D: Disabled
gene.append(Categorical(["D", ">", "<", "=", "CA", "CB",
">I", "=I", "<I", ">R", "=R", "<R"], name=f'buy-oper-{i}'))
return gene
@staticmethod
def buy_strategy_generator(params: Dict[str, Any]) -> Callable:
"""
Define the buy strategy parameters to be used by Hyperopt.
"""
def populate_buy_trend(dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Buy strategy Hyperopt will build and use.
"""
conditions = []
# GUARDS AND TRENDS
for i in range(DNA_SIZE):
OPR = params[f'buy-oper-{i}']
IND = params[f'buy-indicator-{i}']
CRS = params[f'buy-cross-{i}']
INT = params[f'buy-int-{i}']
REAL = params[f'buy-real-{i}']
DFIND = dataframe[IND]
DFCRS = dataframe[CRS]
if OPR == ">":
conditions.append(DFIND > DFCRS)
elif OPR == "=":
conditions.append(np.isclose(DFIND, DFCRS))
elif OPR == "<":
conditions.append(DFIND < DFCRS)
elif OPR == "CA":
conditions.append(qtpylib.crossed_above(DFIND, DFCRS))
elif OPR == "CB":
conditions.append(qtpylib.crossed_below(DFIND, DFCRS))
elif OPR == ">I":
conditions.append(DFIND > INT)
elif OPR == "=I":
conditions.append(DFIND == INT)
elif OPR == "<I":
conditions.append(DFIND < INT)
elif OPR == ">R":
conditions.append(DFIND > REAL)
elif OPR == "=R":
conditions.append(np.isclose(DFIND, REAL))
elif OPR == "<R":
conditions.append(DFIND < REAL)
if conditions:
dataframe.loc[
reduce(lambda x, y: x & y, conditions),
'buy'] = 1
return dataframe
return populate_buy_trend
@ staticmethod
def sell_indicator_space() -> List[Dimension]:
"""
Define your Hyperopt space for searching sell strategy parameters.
"""
gene = list()
for i in range(DNA_SIZE):
gene.append(Categorical(GodGenes, name=f'sell-indicator-{i}'))
gene.append(Categorical(GodGenes, name=f'sell-cross-{i}'))
gene.append(Integer(-1, 101, name=f'sell-int-{i}'))
gene.append(Real(-0.01, 1.01, name=f'sell-real-{i}'))
# Operations
# CA: Crossed Above, CB: Crossed Below,
# I: Integer, R: Real, D: Disabled
gene.append(Categorical(["D", ">", "<", "=", "CA", "CB",
">I", "=I", "<I", ">R", "=R", "<R"], name=f'sell-oper-{i}'))
return gene
@ staticmethod
def sell_strategy_generator(params: Dict[str, Any]) -> Callable:
"""
Define the sell strategy parameters to be used by Hyperopt.
"""
def populate_sell_trend(dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Sell strategy Hyperopt will build and use.
"""
conditions = []
# GUARDS AND TRENDS
for i in range(DNA_SIZE):
OPR = params[f'sell-oper-{i}']
IND = params[f'sell-indicator-{i}']
CRS = params[f'sell-cross-{i}']
INT = params[f'sell-int-{i}']
REAL = params[f'sell-real-{i}']
DFIND = dataframe[IND]
DFCRS = dataframe[CRS]
if OPR == ">":
conditions.append(DFIND > DFCRS)
elif OPR == "=":
conditions.append(np.isclose(DFIND, DFCRS))
elif OPR == "<":
conditions.append(DFIND < DFCRS)
elif OPR == "CA":
conditions.append(qtpylib.crossed_above(DFIND, DFCRS))
elif OPR == "CB":
conditions.append(qtpylib.crossed_below(DFIND, DFCRS))
elif OPR == ">I":
conditions.append(DFIND > INT)
elif OPR == "=I":
conditions.append(DFIND == INT)
elif OPR == "<I":
conditions.append(DFIND < INT)
elif OPR == ">R":
conditions.append(DFIND > REAL)
elif OPR == "=R":
conditions.append(np.isclose(DFIND, REAL))
elif OPR == "<R":
conditions.append(DFIND < REAL)
if conditions:
dataframe.loc[
reduce(lambda x, y: x & y, conditions),
'sell']=1
return dataframe
return populate_sell_trend

668
GodStraJD.py Normal file
View File

@@ -0,0 +1,668 @@
# 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 freqtrade import data
from freqtrade.strategy.parameters import CategoricalParameter, DecimalParameter
from numpy.lib import math
from freqtrade.strategy.interface import IStrategy
from pandas import DataFrame
# --------------------------------
# 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
# TODO: this gene is removed 'MAVP' cuz or error on periods
all_god_genes = {
'Overlap Studies': {
'BBANDS-0', # Bollinger Bands
'BBANDS-1', # Bollinger Bands
'BBANDS-2', # Bollinger Bands
'DEMA', # Double Exponential Moving Average
'EMA', # Exponential Moving Average
'HT_TRENDLINE', # Hilbert Transform - Instantaneous Trendline
'KAMA', # Kaufman Adaptive Moving Average
'MA', # Moving average
'MAMA-0', # MESA Adaptive Moving Average
'MAMA-1', # MESA Adaptive Moving Average
# TODO: Fix this
# 'MAVP', # Moving average with variable period
'MIDPOINT', # MidPoint over period
'MIDPRICE', # Midpoint Price over period
'SAR', # Parabolic SAR
'SAREXT', # Parabolic SAR - Extended
'SMA', # Simple Moving Average
'T3', # Triple Exponential Moving Average (T3)
'TEMA', # Triple Exponential Moving Average
'TRIMA', # Triangular Moving Average
'WMA', # Weighted Moving Average
},
'Momentum Indicators': {
'ADX', # Average Directional Movement Index
'ADXR', # Average Directional Movement Index Rating
'APO', # Absolute Price Oscillator
'AROON-0', # Aroon
'AROON-1', # Aroon
'AROONOSC', # Aroon Oscillator
'BOP', # Balance Of Power
'CCI', # Commodity Channel Index
'CMO', # Chande Momentum Oscillator
'DX', # Directional Movement Index
'MACD-0', # Moving Average Convergence/Divergence
'MACD-1', # Moving Average Convergence/Divergence
'MACD-2', # Moving Average Convergence/Divergence
'MACDEXT-0', # MACD with controllable MA type
'MACDEXT-1', # MACD with controllable MA type
'MACDEXT-2', # MACD with controllable MA type
'MACDFIX-0', # Moving Average Convergence/Divergence Fix 12/26
'MACDFIX-1', # Moving Average Convergence/Divergence Fix 12/26
'MACDFIX-2', # Moving Average Convergence/Divergence Fix 12/26
'MFI', # Money Flow Index
'MINUS_DI', # Minus Directional Indicator
'MINUS_DM', # Minus Directional Movement
'MOM', # Momentum
'PLUS_DI', # Plus Directional Indicator
'PLUS_DM', # Plus Directional Movement
'PPO', # Percentage Price Oscillator
'ROC', # Rate of change : ((price/prevPrice)-1)*100
# Rate of change Percentage: (price-prevPrice)/prevPrice
'ROCP',
'ROCR', # Rate of change ratio: (price/prevPrice)
# Rate of change ratio 100 scale: (price/prevPrice)*100
'ROCR100',
'RSI', # Relative Strength Index
'STOCH-0', # Stochastic
'STOCH-1', # Stochastic
'STOCHF-0', # Stochastic Fast
'STOCHF-1', # Stochastic Fast
'STOCHRSI-0', # Stochastic Relative Strength Index
'STOCHRSI-1', # Stochastic Relative Strength Index
# 1-day Rate-Of-Change (ROC) of a Triple Smooth EMA
'TRIX',
'ULTOSC', # Ultimate Oscillator
'WILLR', # Williams' %R
},
'Volume Indicators': {
'AD', # Chaikin A/D Line
'ADOSC', # Chaikin A/D Oscillator
'OBV', # On Balance Volume
},
'Volatility Indicators': {
'ATR', # Average True Range
'NATR', # Normalized Average True Range
'TRANGE', # True Range
},
'Price Transform': {
'AVGPRICE', # Average Price
'MEDPRICE', # Median Price
'TYPPRICE', # Typical Price
'WCLPRICE', # Weighted Close Price
},
'Cycle Indicators': {
'HT_DCPERIOD', # Hilbert Transform - Dominant Cycle Period
'HT_DCPHASE', # Hilbert Transform - Dominant Cycle Phase
'HT_PHASOR-0', # Hilbert Transform - Phasor Components
'HT_PHASOR-1', # Hilbert Transform - Phasor Components
'HT_SINE-0', # Hilbert Transform - SineWave
'HT_SINE-1', # Hilbert Transform - SineWave
'HT_TRENDMODE', # Hilbert Transform - Trend vs Cycle Mode
},
'Pattern Recognition': {
'CDL2CROWS', # Two Crows
'CDL3BLACKCROWS', # Three Black Crows
'CDL3INSIDE', # Three Inside Up/Down
'CDL3LINESTRIKE', # Three-Line Strike
'CDL3OUTSIDE', # Three Outside Up/Down
'CDL3STARSINSOUTH', # Three Stars In The South
'CDL3WHITESOLDIERS', # Three Advancing White Soldiers
'CDLABANDONEDBABY', # Abandoned Baby
'CDLADVANCEBLOCK', # Advance Block
'CDLBELTHOLD', # Belt-hold
'CDLBREAKAWAY', # Breakaway
'CDLCLOSINGMARUBOZU', # Closing Marubozu
'CDLCONCEALBABYSWALL', # Concealing Baby Swallow
'CDLCOUNTERATTACK', # Counterattack
'CDLDARKCLOUDCOVER', # Dark Cloud Cover
'CDLDOJI', # Doji
'CDLDOJISTAR', # Doji Star
'CDLDRAGONFLYDOJI', # Dragonfly Doji
'CDLENGULFING', # Engulfing Pattern
'CDLEVENINGDOJISTAR', # Evening Doji Star
'CDLEVENINGSTAR', # Evening Star
'CDLGAPSIDESIDEWHITE', # Up/Down-gap side-by-side white lines
'CDLGRAVESTONEDOJI', # Gravestone Doji
'CDLHAMMER', # Hammer
'CDLHANGINGMAN', # Hanging Man
'CDLHARAMI', # Harami Pattern
'CDLHARAMICROSS', # Harami Cross Pattern
'CDLHIGHWAVE', # High-Wave Candle
'CDLHIKKAKE', # Hikkake Pattern
'CDLHIKKAKEMOD', # Modified Hikkake Pattern
'CDLHOMINGPIGEON', # Homing Pigeon
'CDLIDENTICAL3CROWS', # Identical Three Crows
'CDLINNECK', # In-Neck Pattern
'CDLINVERTEDHAMMER', # Inverted Hammer
'CDLKICKING', # Kicking
'CDLKICKINGBYLENGTH', # Kicking - bull/bear determined by the longer marubozu
'CDLLADDERBOTTOM', # Ladder Bottom
'CDLLONGLEGGEDDOJI', # Long Legged Doji
'CDLLONGLINE', # Long Line Candle
'CDLMARUBOZU', # Marubozu
'CDLMATCHINGLOW', # Matching Low
'CDLMATHOLD', # Mat Hold
'CDLMORNINGDOJISTAR', # Morning Doji Star
'CDLMORNINGSTAR', # Morning Star
'CDLONNECK', # On-Neck Pattern
'CDLPIERCING', # Piercing Pattern
'CDLRICKSHAWMAN', # Rickshaw Man
'CDLRISEFALL3METHODS', # Rising/Falling Three Methods
'CDLSEPARATINGLINES', # Separating Lines
'CDLSHOOTINGSTAR', # Shooting Star
'CDLSHORTLINE', # Short Line Candle
'CDLSPINNINGTOP', # Spinning Top
'CDLSTALLEDPATTERN', # Stalled Pattern
'CDLSTICKSANDWICH', # Stick Sandwich
# Takuri (Dragonfly Doji with very long lower shadow)
'CDLTAKURI',
'CDLTASUKIGAP', # Tasuki Gap
'CDLTHRUSTING', # Thrusting Pattern
'CDLTRISTAR', # Tristar Pattern
'CDLUNIQUE3RIVER', # Unique 3 River
'CDLUPSIDEGAP2CROWS', # Upside Gap Two Crows
'CDLXSIDEGAP3METHODS', # Upside/Downside Gap Three Methods
},
'Statistic Functions': {
'BETA', # Beta
'CORREL', # Pearson's Correlation Coefficient (r)
'LINEARREG', # Linear Regression
'LINEARREG_ANGLE', # Linear Regression Angle
'LINEARREG_INTERCEPT', # Linear Regression Intercept
'LINEARREG_SLOPE', # Linear Regression Slope
'STDDEV', # Standard Deviation
'TSF', # Time Series Forecast
'VAR', # Variance
}
}
god_genes = set()
########################### SETTINGS ##############################
# god_genes = {'SMA'}
god_genes |= all_god_genes['Overlap Studies']
god_genes |= all_god_genes['Momentum Indicators']
god_genes |= all_god_genes['Volume Indicators']
god_genes |= all_god_genes['Volatility Indicators']
god_genes |= all_god_genes['Price Transform']
god_genes |= all_god_genes['Cycle Indicators']
god_genes |= all_god_genes['Pattern Recognition']
god_genes |= all_god_genes['Statistic Functions']
timeperiods = [5, 6, 12, 15, 50, 55, 100, 110]
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 = 4
DECIMALS = 1
########################### END SETTINGS ##########################
# DATAFRAME = DataFrame()
god_genes = list(god_genes)
# print('selected indicators for optimzatin: \n', god_genes)
god_genes_with_timeperiod = list()
for god_gene in god_genes:
for timeperiod in timeperiods:
god_genes_with_timeperiod.append(f'{god_gene}-{timeperiod}')
# Let give somethings to CatagoricalParam to Play with them
# When just one thing is inside catagorical lists
# TODO: its Not True Way :)
if len(god_genes) == 1:
god_genes = god_genes*2
if len(timeperiods) == 1:
timeperiods = timeperiods*2
if len(operators) == 1:
operators = operators*2
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):
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] > dataframe[crossed_indicator]
)
elif operator == "=":
condition = (
np.isclose(dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "<":
condition = (
dataframe[indicator] < dataframe[crossed_indicator]
)
elif operator == "C":
condition = (
(qtpylib.crossed_below(dataframe[indicator], dataframe[crossed_indicator])) |
(qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator]))
)
elif operator == "CA":
condition = (
qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "CB":
condition = (
qtpylib.crossed_below(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == ">R":
condition = (
dataframe[indicator] > real_num
)
elif operator == "=R":
condition = (
np.isclose(dataframe[indicator], real_num)
)
elif operator == "<R":
condition = (
dataframe[indicator] < real_num
)
elif operator == "/>R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) > real_num
)
elif operator == "/=R":
condition = (
np.isclose(dataframe[indicator].div(
dataframe[crossed_indicator]), real_num)
)
elif operator == "/<R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) < real_num
)
elif operator == "UT":
condition = (
dataframe[indicator] > dataframe[indicator_trend_sma]
)
elif operator == "DT":
condition = (
dataframe[indicator] < dataframe[indicator_trend_sma]
)
elif operator == "OT":
condition = (
np.isclose(dataframe[indicator], dataframe[indicator_trend_sma])
)
elif operator == "CUT":
condition = (
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] > dataframe[indicator_trend_sma]
)
)
elif operator == "CDT":
condition = (
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] < dataframe[indicator_trend_sma]
)
)
elif operator == "COT":
condition = (
(
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) |
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
) &
(
np.isclose(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
)
return condition, dataframe
class GodStraJD(IStrategy):
# #################### RESULTS PASTE PLACE ####################
# ROI table:
minimal_roi = {
"0": 0.598,
"644": 0.166,
"3269": 0.115,
"7289": 0
}
# Stoploss:
stoploss = -0.128
# Buy hypers
timeframe = '4h'
# Trailing stoploss
trailing_stop = True
trailing_stop_positive = 0.15
trailing_stop_positive_offset = 0.20
trailing_only_offset_is_reached = True
# #################### END OF RESULT PLACE ####################
# TODO: Its not dry code!
# Buy Hyperoptable Parameters/Spaces.
buy_crossed_indicator0 = CategoricalParameter(
god_genes_with_timeperiod, default="ADD-20", space='buy')
buy_crossed_indicator1 = CategoricalParameter(
god_genes_with_timeperiod, default="ASIN-6", space='buy')
buy_crossed_indicator2 = CategoricalParameter(
god_genes_with_timeperiod, default="CDLEVENINGSTAR-50", space='buy')
buy_indicator0 = CategoricalParameter(
god_genes_with_timeperiod, default="SMA-100", space='buy')
buy_indicator1 = CategoricalParameter(
god_genes_with_timeperiod, default="WILLR-50", space='buy')
buy_indicator2 = CategoricalParameter(
god_genes_with_timeperiod, default="CDLHANGINGMAN-20", space='buy')
buy_operator0 = CategoricalParameter(operators, default="/<R", space='buy')
buy_operator1 = CategoricalParameter(operators, default="<R", space='buy')
buy_operator2 = CategoricalParameter(operators, default="CB", space='buy')
buy_real_num0 = DecimalParameter(
0, 1, decimals=DECIMALS, default=0.89009, space='buy')
buy_real_num1 = DecimalParameter(
0, 1, decimals=DECIMALS, default=0.56953, space='buy')
buy_real_num2 = DecimalParameter(
0, 1, decimals=DECIMALS, default=0.38365, space='buy')
# Sell Hyperoptable Parameters/Spaces.
sell_crossed_indicator0 = CategoricalParameter(
god_genes_with_timeperiod, default="CDLSHOOTINGSTAR-150", space='sell')
sell_crossed_indicator1 = CategoricalParameter(
god_genes_with_timeperiod, default="MAMA-1-100", space='sell')
sell_crossed_indicator2 = CategoricalParameter(
god_genes_with_timeperiod, default="CDLMATHOLD-6", space='sell')
sell_indicator0 = CategoricalParameter(
god_genes_with_timeperiod, default="CDLUPSIDEGAP2CROWS-5", space='sell')
sell_indicator1 = CategoricalParameter(
god_genes_with_timeperiod, default="CDLHARAMICROSS-150", space='sell')
sell_indicator2 = CategoricalParameter(
god_genes_with_timeperiod, default="CDL2CROWS-5", space='sell')
sell_operator0 = CategoricalParameter(
operators, default="<R", space='sell')
sell_operator1 = CategoricalParameter(operators, default="D", space='sell')
sell_operator2 = CategoricalParameter(
operators, default="/>R", space='sell')
sell_real_num0 = DecimalParameter(
0, 1, decimals=DECIMALS, default=0.09731, space='sell')
sell_real_num1 = DecimalParameter(
0, 1, decimals=DECIMALS, default=0.81657, space='sell')
sell_real_num2 = DecimalParameter(
0, 1, decimals=DECIMALS, default=0.87267, space='sell')
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
'''
It's good to calculate all indicators in all time periods here and so optimize the strategy.
But this strategy can take much time to generate anything that may not use in his optimization.
I just calculate the specific indicators in specific time period inside buy and sell strategy populator methods if needed.
Also, this method (populate_indicators) just calculates default value of hyperoptable params
so using this method have not big benefits instade of calculating useable things inside buy and sell trand populators
'''
# 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"]
)
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = list()
# TODO: Its not dry code!
buy_indicator = self.buy_indicator0.value
buy_crossed_indicator = self.buy_crossed_indicator0.value
buy_operator = self.buy_operator0.value
buy_real_num = self.buy_real_num0.value
condition, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition)
# backup
buy_indicator = self.buy_indicator1.value
buy_crossed_indicator = self.buy_crossed_indicator1.value
buy_operator = self.buy_operator1.value
buy_real_num = self.buy_real_num1.value
condition, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition)
buy_indicator = self.buy_indicator2.value
buy_crossed_indicator = self.buy_crossed_indicator2.value
buy_operator = self.buy_operator2.value
buy_real_num = self.buy_real_num2.value
condition, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition)
if conditions:
dataframe.loc[
(
(dataframe['close'] < dataframe['bb_lowerband'])
& (dataframe['bb_width'] >= 0.15)
& (dataframe['volume'] > 0)
) |
reduce(lambda x, y: x & y, conditions),
'buy']=1
# print(len(dataframe.keys()))
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = list()
# TODO: Its not dry code!
sell_indicator = self.sell_indicator0.value
sell_crossed_indicator = self.sell_crossed_indicator0.value
sell_operator = self.sell_operator0.value
sell_real_num = self.sell_real_num0.value
condition, dataframe = condition_generator(
dataframe,
sell_operator,
sell_indicator,
sell_crossed_indicator,
sell_real_num
)
conditions.append(condition)
sell_indicator = self.sell_indicator1.value
sell_crossed_indicator = self.sell_crossed_indicator1.value
sell_operator = self.sell_operator1.value
sell_real_num = self.sell_real_num1.value
condition, dataframe = condition_generator(
dataframe,
sell_operator,
sell_indicator,
sell_crossed_indicator,
sell_real_num
)
conditions.append(condition)
sell_indicator = self.sell_indicator2.value
sell_crossed_indicator = self.sell_crossed_indicator2.value
sell_operator = self.sell_operator2.value
sell_real_num = self.sell_real_num2.value
condition, dataframe = condition_generator(
dataframe,
sell_operator,
sell_indicator,
sell_crossed_indicator,
sell_real_num
)
conditions.append(condition)
if conditions:
dataframe.loc[
reduce(lambda x, y: x & y, conditions),
'sell']=1
return dataframe

858
GodStraJD1.py Normal file
View File

@@ -0,0 +1,858 @@
# 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 freqtrade import data
from freqtrade.strategy.parameters import CategoricalParameter, DecimalParameter
from numpy.lib import math
from freqtrade.strategy.interface import IStrategy
from pandas import DataFrame
# --------------------------------
# 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
# TODO: this gene is removed 'MAVP' cuz or error on periods
all_god_genes = {
'Overlap Studies': {
'BBANDS-0', # Bollinger Bands
'BBANDS-1', # Bollinger Bands
'BBANDS-2', # Bollinger Bands
'DEMA', # Double Exponential Moving Average
'EMA', # Exponential Moving Average
'HT_TRENDLINE', # Hilbert Transform - Instantaneous Trendline
'KAMA', # Kaufman Adaptive Moving Average
'MA', # Moving average
'MAMA-0', # MESA Adaptive Moving Average
'MAMA-1', # MESA Adaptive Moving Average
# TODO: Fix this
# 'MAVP', # Moving average with variable period
'MIDPOINT', # MidPoint over period
'MIDPRICE', # Midpoint Price over period
'SAR', # Parabolic SAR
'SAREXT', # Parabolic SAR - Extended
'SMA', # Simple Moving Average
'T3', # Triple Exponential Moving Average (T3)
'TEMA', # Triple Exponential Moving Average
'TRIMA', # Triangular Moving Average
'WMA', # Weighted Moving Average
},
'Momentum Indicators': {
'ADX', # Average Directional Movement Index
'ADXR', # Average Directional Movement Index Rating
'APO', # Absolute Price Oscillator
'AROON-0', # Aroon
'AROON-1', # Aroon
'AROONOSC', # Aroon Oscillator
'BOP', # Balance Of Power
'CCI', # Commodity Channel Index
'CMO', # Chande Momentum Oscillator
'DX', # Directional Movement Index
'MACD-0', # Moving Average Convergence/Divergence
'MACD-1', # Moving Average Convergence/Divergence
'MACD-2', # Moving Average Convergence/Divergence
'MACDEXT-0', # MACD with controllable MA type
'MACDEXT-1', # MACD with controllable MA type
'MACDEXT-2', # MACD with controllable MA type
'MACDFIX-0', # Moving Average Convergence/Divergence Fix 12/26
'MACDFIX-1', # Moving Average Convergence/Divergence Fix 12/26
'MACDFIX-2', # Moving Average Convergence/Divergence Fix 12/26
'MFI', # Money Flow Index
'MINUS_DI', # Minus Directional Indicator
'MINUS_DM', # Minus Directional Movement
'MOM', # Momentum
'PLUS_DI', # Plus Directional Indicator
'PLUS_DM', # Plus Directional Movement
'PPO', # Percentage Price Oscillator
'ROC', # Rate of change : ((price/prevPrice)-1)*100
# Rate of change Percentage: (price-prevPrice)/prevPrice
'ROCP',
'ROCR', # Rate of change ratio: (price/prevPrice)
# Rate of change ratio 100 scale: (price/prevPrice)*100
'ROCR100',
'RSI', # Relative Strength Index
'STOCH-0', # Stochastic
'STOCH-1', # Stochastic
'STOCHF-0', # Stochastic Fast
'STOCHF-1', # Stochastic Fast
'STOCHRSI-0', # Stochastic Relative Strength Index
'STOCHRSI-1', # Stochastic Relative Strength Index
# 1-day Rate-Of-Change (ROC) of a Triple Smooth EMA
'TRIX',
'ULTOSC', # Ultimate Oscillator
'WILLR', # Williams' %R
},
'Volume Indicators': {
'AD', # Chaikin A/D Line
'ADOSC', # Chaikin A/D Oscillator
'OBV', # On Balance Volume
},
'Volatility Indicators': {
'ATR', # Average True Range
'NATR', # Normalized Average True Range
'TRANGE', # True Range
},
'Price Transform': {
'AVGPRICE', # Average Price
'MEDPRICE', # Median Price
'TYPPRICE', # Typical Price
'WCLPRICE', # Weighted Close Price
},
'Cycle Indicators': {
'HT_DCPERIOD', # Hilbert Transform - Dominant Cycle Period
'HT_DCPHASE', # Hilbert Transform - Dominant Cycle Phase
'HT_PHASOR-0', # Hilbert Transform - Phasor Components
'HT_PHASOR-1', # Hilbert Transform - Phasor Components
'HT_SINE-0', # Hilbert Transform - SineWave
'HT_SINE-1', # Hilbert Transform - SineWave
'HT_TRENDMODE', # Hilbert Transform - Trend vs Cycle Mode
},
'Pattern Recognition': {
'CDL2CROWS', # Two Crows
'CDL3BLACKCROWS', # Three Black Crows
'CDL3INSIDE', # Three Inside Up/Down
'CDL3LINESTRIKE', # Three-Line Strike
'CDL3OUTSIDE', # Three Outside Up/Down
'CDL3STARSINSOUTH', # Three Stars In The South
'CDL3WHITESOLDIERS', # Three Advancing White Soldiers
'CDLABANDONEDBABY', # Abandoned Baby
'CDLADVANCEBLOCK', # Advance Block
'CDLBELTHOLD', # Belt-hold
'CDLBREAKAWAY', # Breakaway
'CDLCLOSINGMARUBOZU', # Closing Marubozu
'CDLCONCEALBABYSWALL', # Concealing Baby Swallow
'CDLCOUNTERATTACK', # Counterattack
'CDLDARKCLOUDCOVER', # Dark Cloud Cover
'CDLDOJI', # Doji
'CDLDOJISTAR', # Doji Star
'CDLDRAGONFLYDOJI', # Dragonfly Doji
'CDLENGULFING', # Engulfing Pattern
'CDLEVENINGDOJISTAR', # Evening Doji Star
'CDLEVENINGSTAR', # Evening Star
'CDLGAPSIDESIDEWHITE', # Up/Down-gap side-by-side white lines
'CDLGRAVESTONEDOJI', # Gravestone Doji
'CDLHAMMER', # Hammer
'CDLHANGINGMAN', # Hanging Man
'CDLHARAMI', # Harami Pattern
'CDLHARAMICROSS', # Harami Cross Pattern
'CDLHIGHWAVE', # High-Wave Candle
'CDLHIKKAKE', # Hikkake Pattern
'CDLHIKKAKEMOD', # Modified Hikkake Pattern
'CDLHOMINGPIGEON', # Homing Pigeon
'CDLIDENTICAL3CROWS', # Identical Three Crows
'CDLINNECK', # In-Neck Pattern
'CDLINVERTEDHAMMER', # Inverted Hammer
'CDLKICKING', # Kicking
'CDLKICKINGBYLENGTH', # Kicking - bull/bear determined by the longer marubozu
'CDLLADDERBOTTOM', # Ladder Bottom
'CDLLONGLEGGEDDOJI', # Long Legged Doji
'CDLLONGLINE', # Long Line Candle
'CDLMARUBOZU', # Marubozu
'CDLMATCHINGLOW', # Matching Low
'CDLMATHOLD', # Mat Hold
'CDLMORNINGDOJISTAR', # Morning Doji Star
'CDLMORNINGSTAR', # Morning Star
'CDLONNECK', # On-Neck Pattern
'CDLPIERCING', # Piercing Pattern
'CDLRICKSHAWMAN', # Rickshaw Man
'CDLRISEFALL3METHODS', # Rising/Falling Three Methods
'CDLSEPARATINGLINES', # Separating Lines
'CDLSHOOTINGSTAR', # Shooting Star
'CDLSHORTLINE', # Short Line Candle
'CDLSPINNINGTOP', # Spinning Top
'CDLSTALLEDPATTERN', # Stalled Pattern
'CDLSTICKSANDWICH', # Stick Sandwich
# Takuri (Dragonfly Doji with very long lower shadow)
'CDLTAKURI',
'CDLTASUKIGAP', # Tasuki Gap
'CDLTHRUSTING', # Thrusting Pattern
'CDLTRISTAR', # Tristar Pattern
'CDLUNIQUE3RIVER', # Unique 3 River
'CDLUPSIDEGAP2CROWS', # Upside Gap Two Crows
'CDLXSIDEGAP3METHODS', # Upside/Downside Gap Three Methods
},
'Statistic Functions': {
'BETA', # Beta
'CORREL', # Pearson's Correlation Coefficient (r)
'LINEARREG', # Linear Regression
'LINEARREG_ANGLE', # Linear Regression Angle
'LINEARREG_INTERCEPT', # Linear Regression Intercept
'LINEARREG_SLOPE', # Linear Regression Slope
'STDDEV', # Standard Deviation
'TSF', # Time Series Forecast
'VAR', # Variance
}
}
god_genes = set()
########################### SETTINGS ##############################
# god_genes = {'SMA'}
god_genes |= all_god_genes['Overlap Studies']
god_genes |= all_god_genes['Momentum Indicators']
god_genes |= all_god_genes['Volume Indicators']
god_genes |= all_god_genes['Volatility Indicators']
god_genes |= all_god_genes['Price Transform']
god_genes |= all_god_genes['Cycle Indicators']
god_genes |= all_god_genes['Pattern Recognition']
god_genes |= all_god_genes['Statistic Functions']
timeperiods = [5, 6, 12, 15, 50, 55, 100, 110]
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 = 1
########################### END SETTINGS ##########################
# DATAFRAME = DataFrame()
god_genes = list(god_genes)
# print('selected indicators for optimzatin: \n', god_genes)
god_genes_with_timeperiod = list()
for god_gene in god_genes:
for timeperiod in timeperiods:
god_genes_with_timeperiod.append(f'{god_gene}-{timeperiod}')
# Let give somethings to CatagoricalParam to Play with them
# When just one thing is inside catagorical lists
# TODO: its Not True Way :)
if len(god_genes) == 1:
god_genes = god_genes*2
if len(timeperiods) == 1:
timeperiods = timeperiods*2
if len(operators) == 1:
operators = operators*2
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):
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] > dataframe[crossed_indicator]
)
elif operator == "=":
condition = (
np.isclose(dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "<":
condition = (
dataframe[indicator] < dataframe[crossed_indicator]
)
elif operator == "C":
condition = (
(qtpylib.crossed_below(dataframe[indicator], dataframe[crossed_indicator])) |
(qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator]))
)
elif operator == "CA":
condition = (
qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "CB":
condition = (
qtpylib.crossed_below(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == ">R":
condition = (
dataframe[indicator] > real_num
)
elif operator == "=R":
condition = (
np.isclose(dataframe[indicator], real_num)
)
elif operator == "<R":
condition = (
dataframe[indicator] < real_num
)
elif operator == "/>R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) > real_num
)
elif operator == "/=R":
condition = (
np.isclose(dataframe[indicator].div(
dataframe[crossed_indicator]), real_num)
)
elif operator == "/<R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) < real_num
)
elif operator == "UT":
condition = (
dataframe[indicator] > dataframe[indicator_trend_sma]
)
elif operator == "DT":
condition = (
dataframe[indicator] < dataframe[indicator_trend_sma]
)
elif operator == "OT":
condition = (
np.isclose(dataframe[indicator], dataframe[indicator_trend_sma])
)
elif operator == "CUT":
condition = (
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] > dataframe[indicator_trend_sma]
)
)
elif operator == "CDT":
condition = (
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] < dataframe[indicator_trend_sma]
)
)
elif operator == "COT":
condition = (
(
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) |
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
) &
(
np.isclose(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
)
return condition, dataframe
class GodStraJD1(IStrategy):
# #################### RESULTS PASTE PLACE ####################
# ROI table:
minimal_roi = {
"0": 0.598,
"644": 0.166,
"3269": 0.115,
"7289": 0
}
# Stoploss:
stoploss = -0.128
# Buy hypers
timeframe = '4h'
# Trailing stoploss
trailing_stop = True
trailing_stop_positive = 0.15
trailing_stop_positive_offset = 0.20
trailing_only_offset_is_reached = True
# #################### END OF RESULT PLACE ####################
# TODO: Its not dry code!
# Buy Hyperoptable Parameters/Spaces.
buy_crossed_indicator0 = CategoricalParameter(
god_genes_with_timeperiod, default="ADD-20", space='buy')
buy_crossed_indicator1 = CategoricalParameter(
god_genes_with_timeperiod, default="ASIN-6", space='buy')
buy_crossed_indicator2 = CategoricalParameter(
god_genes_with_timeperiod, default="CDLEVENINGSTAR-50", space='buy')
buy_indicator0 = CategoricalParameter(
god_genes_with_timeperiod, default="SMA-100", space='buy')
buy_indicator1 = CategoricalParameter(
god_genes_with_timeperiod, default="WILLR-50", space='buy')
buy_indicator2 = CategoricalParameter(
god_genes_with_timeperiod, default="CDLHANGINGMAN-20", space='buy')
buy_operator0 = CategoricalParameter(operators, default="/<R", space='buy')
buy_operator1 = CategoricalParameter(operators, default="<R", space='buy')
buy_operator2 = CategoricalParameter(operators, default="CB", space='buy')
buy_real_num0 = DecimalParameter(
0, 1, decimals=DECIMALS, default=0.89009, space='buy')
buy_real_num1 = DecimalParameter(
0, 1, decimals=DECIMALS, default=0.56953, space='buy')
buy_real_num2 = DecimalParameter(
0, 1, decimals=DECIMALS, default=0.38365, space='buy')
# Sell Hyperoptable Parameters/Spaces.
sell_crossed_indicator0 = CategoricalParameter(
god_genes_with_timeperiod, default="CDLSHOOTINGSTAR-150", space='sell')
sell_crossed_indicator1 = CategoricalParameter(
god_genes_with_timeperiod, default="MAMA-1-100", space='sell')
sell_crossed_indicator2 = CategoricalParameter(
god_genes_with_timeperiod, default="CDLMATHOLD-6", space='sell')
sell_indicator0 = CategoricalParameter(
god_genes_with_timeperiod, default="CDLUPSIDEGAP2CROWS-5", space='sell')
sell_indicator1 = CategoricalParameter(
god_genes_with_timeperiod, default="CDLHARAMICROSS-150", space='sell')
sell_indicator2 = CategoricalParameter(
god_genes_with_timeperiod, default="CDL2CROWS-5", space='sell')
sell_operator0 = CategoricalParameter(
operators, default="<R", space='sell')
sell_operator1 = CategoricalParameter(operators, default="D", space='sell')
sell_operator2 = CategoricalParameter(
operators, default="/>R", space='sell')
sell_real_num0 = DecimalParameter(
0, 1, decimals=DECIMALS, default=0.09731, space='sell')
sell_real_num1 = DecimalParameter(
0, 1, decimals=DECIMALS, default=0.81657, space='sell')
sell_real_num2 = DecimalParameter(
0, 1, decimals=DECIMALS, default=0.87267, space='sell')
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
'''
It's good to calculate all indicators in all time periods here and so optimize the strategy.
But this strategy can take much time to generate anything that may not use in his optimization.
I just calculate the specific indicators in specific time period inside buy and sell strategy populator methods if needed.
Also, this method (populate_indicators) just calculates default value of hyperoptable params
so using this method have not big benefits instade of calculating useable things inside buy and sell trand populators
'''
# 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"]
)
# 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"]
)
# # EMA - Exponential Moving Average
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = list()
# TODO: Its not dry code!
buy_indicator = self.buy_indicator0.value
buy_crossed_indicator = self.buy_crossed_indicator0.value
buy_operator = self.buy_operator0.value
buy_real_num = self.buy_real_num0.value
condition, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition)
# backup
buy_indicator = self.buy_indicator1.value
buy_crossed_indicator = self.buy_crossed_indicator1.value
buy_operator = self.buy_operator1.value
buy_real_num = self.buy_real_num1.value
condition, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition)
buy_indicator = self.buy_indicator2.value
buy_crossed_indicator = self.buy_crossed_indicator2.value
buy_operator = self.buy_operator2.value
buy_real_num = self.buy_real_num2.value
condition, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition)
if conditions:
dataframe.loc[
(
(dataframe['close'] < dataframe['bb_lowerband'])
& (dataframe['bb_width'] >= 0.14)
& (dataframe['volume'] > 0)
) |
reduce(lambda x, y: x & y, conditions),
'buy']=1
# print(len(dataframe.keys()))
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = list()
# TODO: Its not dry code!
sell_indicator = self.sell_indicator0.value
sell_crossed_indicator = self.sell_crossed_indicator0.value
sell_operator = self.sell_operator0.value
sell_real_num = self.sell_real_num0.value
condition, dataframe = condition_generator(
dataframe,
sell_operator,
sell_indicator,
sell_crossed_indicator,
sell_real_num
)
conditions.append(condition)
sell_indicator = self.sell_indicator1.value
sell_crossed_indicator = self.sell_crossed_indicator1.value
sell_operator = self.sell_operator1.value
sell_real_num = self.sell_real_num1.value
condition, dataframe = condition_generator(
dataframe,
sell_operator,
sell_indicator,
sell_crossed_indicator,
sell_real_num
)
conditions.append(condition)
sell_indicator = self.sell_indicator2.value
sell_crossed_indicator = self.sell_crossed_indicator2.value
sell_operator = self.sell_operator2.value
sell_real_num = self.sell_real_num2.value
condition, dataframe = condition_generator(
dataframe,
sell_operator,
sell_indicator,
sell_crossed_indicator,
sell_real_num
)
conditions.append(condition)
#dataframe.loc[(dataframe['close'] < dataframe['bb_lowerband']),'sell']=1
if conditions:
dataframe.loc[
(
reduce(lambda x, y: x & y, conditions)
# (
# # StrategyHelperLocal.four_red_candles(dataframe) &
# # dataframe['bb_width'] >= 0.025
# (
# ((dataframe['open'] - dataframe['close'].shift(4)) / dataframe['open'] > 0.01) |
# ((dataframe['open'] - dataframe['close'].shift(5)) / dataframe['open'] > 0.01) |
# ((dataframe['open'] - dataframe['close'].shift(6)) / dataframe['open'] > 0.01) |
# ((dataframe['open'] - dataframe['close'].shift(7)) / dataframe['open'] > 0.01)
# )
# )
),
'sell']=1
return dataframe
class StrategyHelperLocal:
"""
simple helper class to predefine a couple of patterns for our
strategy
"""
@staticmethod
def two_green_candles(dataframe):
"""
evaluates if we are having 7 green candles in a row
:param self:
:param dataframe:
:return:
"""
return (
(dataframe['open'] < dataframe['close']) &
(dataframe['open'].shift(1) < dataframe['close'].shift(1))
# (dataframe['open'].shift(2) < dataframe['close'].shift(2))
)
@staticmethod
def no_more_three_green_candles(dataframe):
"""
evaluates if we are having not more than 3 green candles in a row
:param self:
:param dataframe:
:return:
"""
return not (
(dataframe['open'] < dataframe['close']) &
(dataframe['open'].shift(1) < dataframe['close'].shift(1)) &
(dataframe['open'].shift(2) < dataframe['close'].shift(2)) &
(dataframe['open'].shift(3) < dataframe['close'].shift(3))
)
@staticmethod
def seven_green_candles(dataframe):
"""
evaluates if we are having 7 green candles in a row
:param self:
:param dataframe:
:return:
"""
return (
(dataframe['open'] < dataframe['close']) &
(dataframe['open'].shift(1) < dataframe['close'].shift(1)) &
(dataframe['open'].shift(2) < dataframe['close'].shift(2)) &
(dataframe['open'].shift(3) < dataframe['close'].shift(3)) &
(dataframe['open'].shift(4) < dataframe['close'].shift(4)) &
(dataframe['open'].shift(5) < dataframe['close'].shift(5)) &
(dataframe['open'].shift(6) < dataframe['close'].shift(6)) &
(dataframe['open'].shift(7) < dataframe['close'].shift(7))
)
@staticmethod
def eight_green_candles(dataframe):
"""
evaluates if we are having 8 green candles in a row
:param self:
:param dataframe:
:return:
"""
return (
(dataframe['open'] < dataframe['close']) &
(dataframe['open'].shift(1) < dataframe['close'].shift(1)) &
(dataframe['open'].shift(2) < dataframe['close'].shift(2)) &
(dataframe['open'].shift(3) < dataframe['close'].shift(3)) &
(dataframe['open'].shift(4) < dataframe['close'].shift(4)) &
(dataframe['open'].shift(5) < dataframe['close'].shift(5)) &
(dataframe['open'].shift(6) < dataframe['close'].shift(6)) &
(dataframe['open'].shift(7) < dataframe['close'].shift(7)) &
(dataframe['open'].shift(8) < dataframe['close'].shift(8))
)
@staticmethod
def two_red_candles(dataframe, shift=0):
"""
evaluates if we are having 8 red candles in a row
:param self:
:param dataframe:
:param shift: shift the pattern by n
:return:
"""
return (
(dataframe['open'].shift(shift) > dataframe['close'].shift(shift)) &
(dataframe['open'].shift(1 + shift) > dataframe['close'].shift(1 + shift))
# (dataframe['open'].shift(2 + shift) > dataframe['close'].shift(2 + shift)) &
# (dataframe['open'].shift(5 + shift) > dataframe['close'].shift(5 + shift)) &
# (dataframe['open'].shift(6 + shift) > dataframe['close'].shift(6 + shift)) &
# (dataframe['open'].shift(7 + shift) > dataframe['close'].shift(7 + shift)) &
# (dataframe['open'].shift(8 + shift) > dataframe['close'].shift(8 + shift))
)
@staticmethod
def four_red_candles(dataframe, shift=0):
"""
evaluates if we are having 8 red candles in a row
:param self:
:param dataframe:
:param shift: shift the pattern by n
:return:
"""
return (
(dataframe['open'].shift(shift) > dataframe['close'].shift(shift)) &
(dataframe['open'].shift(1 + shift) > dataframe['close'].shift(1 + shift)) &
(dataframe['open'].shift(2 + shift) > dataframe['close'].shift(2 + shift)) &
(dataframe['open'].shift(3 + shift) > dataframe['close'].shift(3 + shift)) &
(dataframe['open'].shift(4 + shift) > dataframe['close'].shift(4 + shift))
# (dataframe['open'].shift(5 + shift) > dataframe['close'].shift(5 + shift)) &
# (dataframe['open'].shift(6 + shift) > dataframe['close'].shift(6 + shift)) &
# (dataframe['open'].shift(7 + shift) > dataframe['close'].shift(7 + shift)) &
# (dataframe['open'].shift(8 + shift) > dataframe['close'].shift(8 + shift))
)
@staticmethod
def two_green_one_red_candle(dataframe):
"""
evaluates if we are having a red candle and 4 previous green
:param self:
:param dataframe:
:return:
"""
return (
(dataframe['open'] < dataframe['close']) &
(dataframe['open'].shift(1) < dataframe['close'].shift(1)) &
(dataframe['open'].shift(2) > dataframe['close'].shift(2))
)
@staticmethod
def four_green_one_red_candle(dataframe):
"""
evaluates if we are having a red candle and 4 previous green
:param self:
:param dataframe:
:return:
"""
return (
(dataframe['open'] > dataframe['close']) &
(dataframe['open'].shift(1) < dataframe['close'].shift(1)) &
(dataframe['open'].shift(2) < dataframe['close'].shift(2)) &
(dataframe['open'].shift(3) < dataframe['close'].shift(3)) &
(dataframe['open'].shift(4) < dataframe['close'].shift(4))
)
@staticmethod
def four_red_one_green_candle(dataframe):
"""
evaluates if we are having a green candle and 4 previous red
:param self:
:param dataframe:
:return:
"""
return (
(dataframe['open'] < dataframe['close']) &
(dataframe['open'].shift(1) > dataframe['close'].shift(1)) &
(dataframe['open'].shift(2) > dataframe['close'].shift(2)) &
(dataframe['open'].shift(3) > dataframe['close'].shift(3)) &
(dataframe['open'].shift(4) > dataframe['close'].shift(4))
)

848
GodStraJD2.py Normal file
View File

@@ -0,0 +1,848 @@
# 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 freqtrade import data
from freqtrade.strategy.parameters import CategoricalParameter, DecimalParameter
from numpy.lib import math
from freqtrade.strategy.interface import IStrategy
from pandas import DataFrame
# --------------------------------
# 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
# TODO: this gene is removed 'MAVP' cuz or error on periods
all_god_genes = {
'Overlap Studies': {
'BBANDS-0', # Bollinger Bands
'BBANDS-1', # Bollinger Bands
'BBANDS-2', # Bollinger Bands
'DEMA', # Double Exponential Moving Average
'EMA', # Exponential Moving Average
'HT_TRENDLINE', # Hilbert Transform - Instantaneous Trendline
'KAMA', # Kaufman Adaptive Moving Average
'MA', # Moving average
'MAMA-0', # MESA Adaptive Moving Average
'MAMA-1', # MESA Adaptive Moving Average
# TODO: Fix this
# 'MAVP', # Moving average with variable period
'MIDPOINT', # MidPoint over period
'MIDPRICE', # Midpoint Price over period
'SAR', # Parabolic SAR
'SAREXT', # Parabolic SAR - Extended
'SMA', # Simple Moving Average
'T3', # Triple Exponential Moving Average (T3)
'TEMA', # Triple Exponential Moving Average
'TRIMA', # Triangular Moving Average
'WMA', # Weighted Moving Average
},
'Momentum Indicators': {
'ADX', # Average Directional Movement Index
'ADXR', # Average Directional Movement Index Rating
'APO', # Absolute Price Oscillator
'AROON-0', # Aroon
'AROON-1', # Aroon
'AROONOSC', # Aroon Oscillator
'BOP', # Balance Of Power
'CCI', # Commodity Channel Index
'CMO', # Chande Momentum Oscillator
'DX', # Directional Movement Index
'MACD-0', # Moving Average Convergence/Divergence
'MACD-1', # Moving Average Convergence/Divergence
'MACD-2', # Moving Average Convergence/Divergence
'MACDEXT-0', # MACD with controllable MA type
'MACDEXT-1', # MACD with controllable MA type
'MACDEXT-2', # MACD with controllable MA type
'MACDFIX-0', # Moving Average Convergence/Divergence Fix 12/26
'MACDFIX-1', # Moving Average Convergence/Divergence Fix 12/26
'MACDFIX-2', # Moving Average Convergence/Divergence Fix 12/26
'MFI', # Money Flow Index
'MINUS_DI', # Minus Directional Indicator
'MINUS_DM', # Minus Directional Movement
'MOM', # Momentum
'PLUS_DI', # Plus Directional Indicator
'PLUS_DM', # Plus Directional Movement
'PPO', # Percentage Price Oscillator
'ROC', # Rate of change : ((price/prevPrice)-1)*100
# Rate of change Percentage: (price-prevPrice)/prevPrice
'ROCP',
'ROCR', # Rate of change ratio: (price/prevPrice)
# Rate of change ratio 100 scale: (price/prevPrice)*100
'ROCR100',
'RSI', # Relative Strength Index
'STOCH-0', # Stochastic
'STOCH-1', # Stochastic
'STOCHF-0', # Stochastic Fast
'STOCHF-1', # Stochastic Fast
'STOCHRSI-0', # Stochastic Relative Strength Index
'STOCHRSI-1', # Stochastic Relative Strength Index
# 1-day Rate-Of-Change (ROC) of a Triple Smooth EMA
'TRIX',
'ULTOSC', # Ultimate Oscillator
'WILLR', # Williams' %R
},
'Volume Indicators': {
'AD', # Chaikin A/D Line
'ADOSC', # Chaikin A/D Oscillator
'OBV', # On Balance Volume
},
'Volatility Indicators': {
'ATR', # Average True Range
'NATR', # Normalized Average True Range
'TRANGE', # True Range
},
'Price Transform': {
'AVGPRICE', # Average Price
'MEDPRICE', # Median Price
'TYPPRICE', # Typical Price
'WCLPRICE', # Weighted Close Price
},
'Cycle Indicators': {
'HT_DCPERIOD', # Hilbert Transform - Dominant Cycle Period
'HT_DCPHASE', # Hilbert Transform - Dominant Cycle Phase
'HT_PHASOR-0', # Hilbert Transform - Phasor Components
'HT_PHASOR-1', # Hilbert Transform - Phasor Components
'HT_SINE-0', # Hilbert Transform - SineWave
'HT_SINE-1', # Hilbert Transform - SineWave
'HT_TRENDMODE', # Hilbert Transform - Trend vs Cycle Mode
},
'Pattern Recognition': {
'CDL2CROWS', # Two Crows
'CDL3BLACKCROWS', # Three Black Crows
'CDL3INSIDE', # Three Inside Up/Down
'CDL3LINESTRIKE', # Three-Line Strike
'CDL3OUTSIDE', # Three Outside Up/Down
'CDL3STARSINSOUTH', # Three Stars In The South
'CDL3WHITESOLDIERS', # Three Advancing White Soldiers
'CDLABANDONEDBABY', # Abandoned Baby
'CDLADVANCEBLOCK', # Advance Block
'CDLBELTHOLD', # Belt-hold
'CDLBREAKAWAY', # Breakaway
'CDLCLOSINGMARUBOZU', # Closing Marubozu
'CDLCONCEALBABYSWALL', # Concealing Baby Swallow
'CDLCOUNTERATTACK', # Counterattack
'CDLDARKCLOUDCOVER', # Dark Cloud Cover
'CDLDOJI', # Doji
'CDLDOJISTAR', # Doji Star
'CDLDRAGONFLYDOJI', # Dragonfly Doji
'CDLENGULFING', # Engulfing Pattern
'CDLEVENINGDOJISTAR', # Evening Doji Star
'CDLEVENINGSTAR', # Evening Star
'CDLGAPSIDESIDEWHITE', # Up/Down-gap side-by-side white lines
'CDLGRAVESTONEDOJI', # Gravestone Doji
'CDLHAMMER', # Hammer
'CDLHANGINGMAN', # Hanging Man
'CDLHARAMI', # Harami Pattern
'CDLHARAMICROSS', # Harami Cross Pattern
'CDLHIGHWAVE', # High-Wave Candle
'CDLHIKKAKE', # Hikkake Pattern
'CDLHIKKAKEMOD', # Modified Hikkake Pattern
'CDLHOMINGPIGEON', # Homing Pigeon
'CDLIDENTICAL3CROWS', # Identical Three Crows
'CDLINNECK', # In-Neck Pattern
'CDLINVERTEDHAMMER', # Inverted Hammer
'CDLKICKING', # Kicking
'CDLKICKINGBYLENGTH', # Kicking - bull/bear determined by the longer marubozu
'CDLLADDERBOTTOM', # Ladder Bottom
'CDLLONGLEGGEDDOJI', # Long Legged Doji
'CDLLONGLINE', # Long Line Candle
'CDLMARUBOZU', # Marubozu
'CDLMATCHINGLOW', # Matching Low
'CDLMATHOLD', # Mat Hold
'CDLMORNINGDOJISTAR', # Morning Doji Star
'CDLMORNINGSTAR', # Morning Star
'CDLONNECK', # On-Neck Pattern
'CDLPIERCING', # Piercing Pattern
'CDLRICKSHAWMAN', # Rickshaw Man
'CDLRISEFALL3METHODS', # Rising/Falling Three Methods
'CDLSEPARATINGLINES', # Separating Lines
'CDLSHOOTINGSTAR', # Shooting Star
'CDLSHORTLINE', # Short Line Candle
'CDLSPINNINGTOP', # Spinning Top
'CDLSTALLEDPATTERN', # Stalled Pattern
'CDLSTICKSANDWICH', # Stick Sandwich
# Takuri (Dragonfly Doji with very long lower shadow)
'CDLTAKURI',
'CDLTASUKIGAP', # Tasuki Gap
'CDLTHRUSTING', # Thrusting Pattern
'CDLTRISTAR', # Tristar Pattern
'CDLUNIQUE3RIVER', # Unique 3 River
'CDLUPSIDEGAP2CROWS', # Upside Gap Two Crows
'CDLXSIDEGAP3METHODS', # Upside/Downside Gap Three Methods
},
'Statistic Functions': {
'BETA', # Beta
'CORREL', # Pearson's Correlation Coefficient (r)
'LINEARREG', # Linear Regression
'LINEARREG_ANGLE', # Linear Regression Angle
'LINEARREG_INTERCEPT', # Linear Regression Intercept
'LINEARREG_SLOPE', # Linear Regression Slope
'STDDEV', # Standard Deviation
'TSF', # Time Series Forecast
'VAR', # Variance
}
}
god_genes = set()
########################### SETTINGS ##############################
# god_genes = {'SMA'}
god_genes |= all_god_genes['Overlap Studies']
god_genes |= all_god_genes['Momentum Indicators']
god_genes |= all_god_genes['Volume Indicators']
god_genes |= all_god_genes['Volatility Indicators']
god_genes |= all_god_genes['Price Transform']
god_genes |= all_god_genes['Cycle Indicators']
god_genes |= all_god_genes['Pattern Recognition']
god_genes |= all_god_genes['Statistic Functions']
timeperiods = [5, 6, 12, 15, 50, 55, 100, 110]
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 = 1
########################### END SETTINGS ##########################
# DATAFRAME = DataFrame()
god_genes = list(god_genes)
# print('selected indicators for optimzatin: \n', god_genes)
god_genes_with_timeperiod = list()
for god_gene in god_genes:
for timeperiod in timeperiods:
god_genes_with_timeperiod.append(f'{god_gene}-{timeperiod}')
# Let give somethings to CatagoricalParam to Play with them
# When just one thing is inside catagorical lists
# TODO: its Not True Way :)
if len(god_genes) == 1:
god_genes = god_genes*2
if len(timeperiods) == 1:
timeperiods = timeperiods*2
if len(operators) == 1:
operators = operators*2
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):
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] > dataframe[crossed_indicator]
)
elif operator == "=":
condition = (
np.isclose(dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "<":
condition = (
dataframe[indicator] < dataframe[crossed_indicator]
)
elif operator == "C":
condition = (
(qtpylib.crossed_below(dataframe[indicator], dataframe[crossed_indicator])) |
(qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator]))
)
elif operator == "CA":
condition = (
qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "CB":
condition = (
qtpylib.crossed_below(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == ">R":
condition = (
dataframe[indicator] > real_num
)
elif operator == "=R":
condition = (
np.isclose(dataframe[indicator], real_num)
)
elif operator == "<R":
condition = (
dataframe[indicator] < real_num
)
elif operator == "/>R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) > real_num
)
elif operator == "/=R":
condition = (
np.isclose(dataframe[indicator].div(
dataframe[crossed_indicator]), real_num)
)
elif operator == "/<R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) < real_num
)
elif operator == "UT":
condition = (
dataframe[indicator] > dataframe[indicator_trend_sma]
)
elif operator == "DT":
condition = (
dataframe[indicator] < dataframe[indicator_trend_sma]
)
elif operator == "OT":
condition = (
np.isclose(dataframe[indicator], dataframe[indicator_trend_sma])
)
elif operator == "CUT":
condition = (
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] > dataframe[indicator_trend_sma]
)
)
elif operator == "CDT":
condition = (
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] < dataframe[indicator_trend_sma]
)
)
elif operator == "COT":
condition = (
(
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) |
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
) &
(
np.isclose(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
)
return condition, dataframe
class GodStraJD2(IStrategy):
# #################### RESULTS PASTE PLACE ####################
# ROI table:
minimal_roi = {
"0": 0.598,
"644": 0.166,
"3269": 0.115,
"7289": 0
}
# Stoploss:
stoploss = -0.128
# Buy hypers
timeframe = '4h'
# Trailing stoploss
trailing_stop = True
trailing_stop_positive = 0.15
trailing_stop_positive_offset = 0.20
trailing_only_offset_is_reached = True
# #################### END OF RESULT PLACE ####################
# TODO: Its not dry code!
# Buy Hyperoptable Parameters/Spaces.
buy_crossed_indicator0 = CategoricalParameter(
god_genes_with_timeperiod, default="ADD-20", space='buy')
buy_crossed_indicator1 = CategoricalParameter(
god_genes_with_timeperiod, default="ASIN-6", space='buy')
buy_crossed_indicator2 = CategoricalParameter(
god_genes_with_timeperiod, default="CDLEVENINGSTAR-50", space='buy')
buy_indicator0 = CategoricalParameter(
god_genes_with_timeperiod, default="SMA-100", space='buy')
buy_indicator1 = CategoricalParameter(
god_genes_with_timeperiod, default="WILLR-50", space='buy')
buy_indicator2 = CategoricalParameter(
god_genes_with_timeperiod, default="CDLHANGINGMAN-20", space='buy')
buy_operator0 = CategoricalParameter(operators, default="/<R", space='buy')
buy_operator1 = CategoricalParameter(operators, default="<R", space='buy')
buy_operator2 = CategoricalParameter(operators, default="CB", space='buy')
buy_real_num0 = DecimalParameter(
0, 1, decimals=DECIMALS, default=0.89009, space='buy')
buy_real_num1 = DecimalParameter(
0, 1, decimals=DECIMALS, default=0.56953, space='buy')
buy_real_num2 = DecimalParameter(
0, 1, decimals=DECIMALS, default=0.38365, space='buy')
# Sell Hyperoptable Parameters/Spaces.
sell_crossed_indicator0 = CategoricalParameter(
god_genes_with_timeperiod, default="CDLSHOOTINGSTAR-150", space='sell')
sell_crossed_indicator1 = CategoricalParameter(
god_genes_with_timeperiod, default="MAMA-1-100", space='sell')
sell_crossed_indicator2 = CategoricalParameter(
god_genes_with_timeperiod, default="CDLMATHOLD-6", space='sell')
sell_indicator0 = CategoricalParameter(
god_genes_with_timeperiod, default="CDLUPSIDEGAP2CROWS-5", space='sell')
sell_indicator1 = CategoricalParameter(
god_genes_with_timeperiod, default="CDLHARAMICROSS-150", space='sell')
sell_indicator2 = CategoricalParameter(
god_genes_with_timeperiod, default="CDL2CROWS-5", space='sell')
sell_operator0 = CategoricalParameter(
operators, default="<R", space='sell')
sell_operator1 = CategoricalParameter(operators, default="D", space='sell')
sell_operator2 = CategoricalParameter(
operators, default="/>R", space='sell')
sell_real_num0 = DecimalParameter(
0, 1, decimals=DECIMALS, default=0.09731, space='sell')
sell_real_num1 = DecimalParameter(
0, 1, decimals=DECIMALS, default=0.81657, space='sell')
sell_real_num2 = DecimalParameter(
0, 1, decimals=DECIMALS, default=0.87267, space='sell')
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
'''
It's good to calculate all indicators in all time periods here and so optimize the strategy.
But this strategy can take much time to generate anything that may not use in his optimization.
I just calculate the specific indicators in specific time period inside buy and sell strategy populator methods if needed.
Also, this method (populate_indicators) just calculates default value of hyperoptable params
so using this method have not big benefits instade of calculating useable things inside buy and sell trand populators
'''
# 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"]
)
# 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"]
)
# # EMA - Exponential Moving Average
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = list()
# TODO: Its not dry code!
buy_indicator = self.buy_indicator0.value
buy_crossed_indicator = self.buy_crossed_indicator0.value
buy_operator = self.buy_operator0.value
buy_real_num = self.buy_real_num0.value
condition, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition)
# backup
buy_indicator = self.buy_indicator1.value
buy_crossed_indicator = self.buy_crossed_indicator1.value
buy_operator = self.buy_operator1.value
buy_real_num = self.buy_real_num1.value
condition, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition)
buy_indicator = self.buy_indicator2.value
buy_crossed_indicator = self.buy_crossed_indicator2.value
buy_operator = self.buy_operator2.value
buy_real_num = self.buy_real_num2.value
condition, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition)
if conditions:
dataframe.loc[
(
(dataframe['close'] < dataframe['bb_lowerband'])
& (dataframe['bb_width'] >= 0.13)
& (dataframe['volume'] > 0)
) |
reduce(lambda x, y: x & y, conditions),
'buy']=1
# print(len(dataframe.keys()))
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = list()
# TODO: Its not dry code!
sell_indicator = self.sell_indicator0.value
sell_crossed_indicator = self.sell_crossed_indicator0.value
sell_operator = self.sell_operator0.value
sell_real_num = self.sell_real_num0.value
condition, dataframe = condition_generator(
dataframe,
sell_operator,
sell_indicator,
sell_crossed_indicator,
sell_real_num
)
conditions.append(condition)
sell_indicator = self.sell_indicator1.value
sell_crossed_indicator = self.sell_crossed_indicator1.value
sell_operator = self.sell_operator1.value
sell_real_num = self.sell_real_num1.value
condition, dataframe = condition_generator(
dataframe,
sell_operator,
sell_indicator,
sell_crossed_indicator,
sell_real_num
)
conditions.append(condition)
sell_indicator = self.sell_indicator2.value
sell_crossed_indicator = self.sell_crossed_indicator2.value
sell_operator = self.sell_operator2.value
sell_real_num = self.sell_real_num2.value
condition, dataframe = condition_generator(
dataframe,
sell_operator,
sell_indicator,
sell_crossed_indicator,
sell_real_num
)
conditions.append(condition)
#dataframe.loc[(dataframe['close'] < dataframe['bb_lowerband']),'sell']=1
if conditions:
dataframe.loc[
(
reduce(lambda x, y: x & y, conditions)
),
'sell']=1
return dataframe
class StrategyHelperLocal:
"""
simple helper class to predefine a couple of patterns for our
strategy
"""
@staticmethod
def two_green_candles(dataframe):
"""
evaluates if we are having 7 green candles in a row
:param self:
:param dataframe:
:return:
"""
return (
(dataframe['open'] < dataframe['close']) &
(dataframe['open'].shift(1) < dataframe['close'].shift(1))
# (dataframe['open'].shift(2) < dataframe['close'].shift(2))
)
@staticmethod
def no_more_three_green_candles(dataframe):
"""
evaluates if we are having not more than 3 green candles in a row
:param self:
:param dataframe:
:return:
"""
return not (
(dataframe['open'] < dataframe['close']) &
(dataframe['open'].shift(1) < dataframe['close'].shift(1)) &
(dataframe['open'].shift(2) < dataframe['close'].shift(2)) &
(dataframe['open'].shift(3) < dataframe['close'].shift(3))
)
@staticmethod
def seven_green_candles(dataframe):
"""
evaluates if we are having 7 green candles in a row
:param self:
:param dataframe:
:return:
"""
return (
(dataframe['open'] < dataframe['close']) &
(dataframe['open'].shift(1) < dataframe['close'].shift(1)) &
(dataframe['open'].shift(2) < dataframe['close'].shift(2)) &
(dataframe['open'].shift(3) < dataframe['close'].shift(3)) &
(dataframe['open'].shift(4) < dataframe['close'].shift(4)) &
(dataframe['open'].shift(5) < dataframe['close'].shift(5)) &
(dataframe['open'].shift(6) < dataframe['close'].shift(6)) &
(dataframe['open'].shift(7) < dataframe['close'].shift(7))
)
@staticmethod
def eight_green_candles(dataframe):
"""
evaluates if we are having 8 green candles in a row
:param self:
:param dataframe:
:return:
"""
return (
(dataframe['open'] < dataframe['close']) &
(dataframe['open'].shift(1) < dataframe['close'].shift(1)) &
(dataframe['open'].shift(2) < dataframe['close'].shift(2)) &
(dataframe['open'].shift(3) < dataframe['close'].shift(3)) &
(dataframe['open'].shift(4) < dataframe['close'].shift(4)) &
(dataframe['open'].shift(5) < dataframe['close'].shift(5)) &
(dataframe['open'].shift(6) < dataframe['close'].shift(6)) &
(dataframe['open'].shift(7) < dataframe['close'].shift(7)) &
(dataframe['open'].shift(8) < dataframe['close'].shift(8))
)
@staticmethod
def two_red_candles(dataframe, shift=0):
"""
evaluates if we are having 8 red candles in a row
:param self:
:param dataframe:
:param shift: shift the pattern by n
:return:
"""
return (
(dataframe['open'].shift(shift) > dataframe['close'].shift(shift)) &
(dataframe['open'].shift(1 + shift) > dataframe['close'].shift(1 + shift))
# (dataframe['open'].shift(2 + shift) > dataframe['close'].shift(2 + shift)) &
# (dataframe['open'].shift(5 + shift) > dataframe['close'].shift(5 + shift)) &
# (dataframe['open'].shift(6 + shift) > dataframe['close'].shift(6 + shift)) &
# (dataframe['open'].shift(7 + shift) > dataframe['close'].shift(7 + shift)) &
# (dataframe['open'].shift(8 + shift) > dataframe['close'].shift(8 + shift))
)
@staticmethod
def four_red_candles(dataframe, shift=0):
"""
evaluates if we are having 8 red candles in a row
:param self:
:param dataframe:
:param shift: shift the pattern by n
:return:
"""
return (
(dataframe['open'].shift(shift) > dataframe['close'].shift(shift)) &
(dataframe['open'].shift(1 + shift) > dataframe['close'].shift(1 + shift)) &
(dataframe['open'].shift(2 + shift) > dataframe['close'].shift(2 + shift)) &
(dataframe['open'].shift(3 + shift) > dataframe['close'].shift(3 + shift)) &
(dataframe['open'].shift(4 + shift) > dataframe['close'].shift(4 + shift))
# (dataframe['open'].shift(5 + shift) > dataframe['close'].shift(5 + shift)) &
# (dataframe['open'].shift(6 + shift) > dataframe['close'].shift(6 + shift)) &
# (dataframe['open'].shift(7 + shift) > dataframe['close'].shift(7 + shift)) &
# (dataframe['open'].shift(8 + shift) > dataframe['close'].shift(8 + shift))
)
@staticmethod
def two_green_one_red_candle(dataframe):
"""
evaluates if we are having a red candle and 4 previous green
:param self:
:param dataframe:
:return:
"""
return (
(dataframe['open'] < dataframe['close']) &
(dataframe['open'].shift(1) < dataframe['close'].shift(1)) &
(dataframe['open'].shift(2) > dataframe['close'].shift(2))
)
@staticmethod
def four_green_one_red_candle(dataframe):
"""
evaluates if we are having a red candle and 4 previous green
:param self:
:param dataframe:
:return:
"""
return (
(dataframe['open'] > dataframe['close']) &
(dataframe['open'].shift(1) < dataframe['close'].shift(1)) &
(dataframe['open'].shift(2) < dataframe['close'].shift(2)) &
(dataframe['open'].shift(3) < dataframe['close'].shift(3)) &
(dataframe['open'].shift(4) < dataframe['close'].shift(4))
)
@staticmethod
def four_red_one_green_candle(dataframe):
"""
evaluates if we are having a green candle and 4 previous red
:param self:
:param dataframe:
:return:
"""
return (
(dataframe['open'] < dataframe['close']) &
(dataframe['open'].shift(1) > dataframe['close'].shift(1)) &
(dataframe['open'].shift(2) > dataframe['close'].shift(2)) &
(dataframe['open'].shift(3) > dataframe['close'].shift(3)) &
(dataframe['open'].shift(4) > dataframe['close'].shift(4))
)

863
GodStraJD3.py Normal file
View File

@@ -0,0 +1,863 @@
# 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 freqtrade import data
from freqtrade.strategy.parameters import CategoricalParameter, DecimalParameter
from numpy.lib import math
from freqtrade.strategy.interface import IStrategy
from pandas import DataFrame
# --------------------------------
# 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
# TODO: this gene is removed 'MAVP' cuz or error on periods
all_god_genes = {
'Overlap Studies': {
'BBANDS-0', # Bollinger Bands
'BBANDS-1', # Bollinger Bands
'BBANDS-2', # Bollinger Bands
'DEMA', # Double Exponential Moving Average
'EMA', # Exponential Moving Average
'HT_TRENDLINE', # Hilbert Transform - Instantaneous Trendline
'KAMA', # Kaufman Adaptive Moving Average
'MA', # Moving average
'MAMA-0', # MESA Adaptive Moving Average
'MAMA-1', # MESA Adaptive Moving Average
# TODO: Fix this
# 'MAVP', # Moving average with variable period
'MIDPOINT', # MidPoint over period
'MIDPRICE', # Midpoint Price over period
'SAR', # Parabolic SAR
'SAREXT', # Parabolic SAR - Extended
'SMA', # Simple Moving Average
'T3', # Triple Exponential Moving Average (T3)
'TEMA', # Triple Exponential Moving Average
'TRIMA', # Triangular Moving Average
'WMA', # Weighted Moving Average
},
'Momentum Indicators': {
'ADX', # Average Directional Movement Index
'ADXR', # Average Directional Movement Index Rating
'APO', # Absolute Price Oscillator
'AROON-0', # Aroon
'AROON-1', # Aroon
'AROONOSC', # Aroon Oscillator
'BOP', # Balance Of Power
'CCI', # Commodity Channel Index
'CMO', # Chande Momentum Oscillator
'DX', # Directional Movement Index
'MACD-0', # Moving Average Convergence/Divergence
'MACD-1', # Moving Average Convergence/Divergence
'MACD-2', # Moving Average Convergence/Divergence
'MACDEXT-0', # MACD with controllable MA type
'MACDEXT-1', # MACD with controllable MA type
'MACDEXT-2', # MACD with controllable MA type
'MACDFIX-0', # Moving Average Convergence/Divergence Fix 12/26
'MACDFIX-1', # Moving Average Convergence/Divergence Fix 12/26
'MACDFIX-2', # Moving Average Convergence/Divergence Fix 12/26
'MFI', # Money Flow Index
'MINUS_DI', # Minus Directional Indicator
'MINUS_DM', # Minus Directional Movement
'MOM', # Momentum
'PLUS_DI', # Plus Directional Indicator
'PLUS_DM', # Plus Directional Movement
'PPO', # Percentage Price Oscillator
'ROC', # Rate of change : ((price/prevPrice)-1)*100
# Rate of change Percentage: (price-prevPrice)/prevPrice
'ROCP',
'ROCR', # Rate of change ratio: (price/prevPrice)
# Rate of change ratio 100 scale: (price/prevPrice)*100
'ROCR100',
'RSI', # Relative Strength Index
'STOCH-0', # Stochastic
'STOCH-1', # Stochastic
'STOCHF-0', # Stochastic Fast
'STOCHF-1', # Stochastic Fast
'STOCHRSI-0', # Stochastic Relative Strength Index
'STOCHRSI-1', # Stochastic Relative Strength Index
# 1-day Rate-Of-Change (ROC) of a Triple Smooth EMA
'TRIX',
'ULTOSC', # Ultimate Oscillator
'WILLR', # Williams' %R
},
'Volume Indicators': {
'AD', # Chaikin A/D Line
'ADOSC', # Chaikin A/D Oscillator
'OBV', # On Balance Volume
},
'Volatility Indicators': {
'ATR', # Average True Range
'NATR', # Normalized Average True Range
'TRANGE', # True Range
},
'Price Transform': {
'AVGPRICE', # Average Price
'MEDPRICE', # Median Price
'TYPPRICE', # Typical Price
'WCLPRICE', # Weighted Close Price
},
'Cycle Indicators': {
'HT_DCPERIOD', # Hilbert Transform - Dominant Cycle Period
'HT_DCPHASE', # Hilbert Transform - Dominant Cycle Phase
'HT_PHASOR-0', # Hilbert Transform - Phasor Components
'HT_PHASOR-1', # Hilbert Transform - Phasor Components
'HT_SINE-0', # Hilbert Transform - SineWave
'HT_SINE-1', # Hilbert Transform - SineWave
'HT_TRENDMODE', # Hilbert Transform - Trend vs Cycle Mode
},
'Pattern Recognition': {
'CDL2CROWS', # Two Crows
'CDL3BLACKCROWS', # Three Black Crows
'CDL3INSIDE', # Three Inside Up/Down
'CDL3LINESTRIKE', # Three-Line Strike
'CDL3OUTSIDE', # Three Outside Up/Down
'CDL3STARSINSOUTH', # Three Stars In The South
'CDL3WHITESOLDIERS', # Three Advancing White Soldiers
'CDLABANDONEDBABY', # Abandoned Baby
'CDLADVANCEBLOCK', # Advance Block
'CDLBELTHOLD', # Belt-hold
'CDLBREAKAWAY', # Breakaway
'CDLCLOSINGMARUBOZU', # Closing Marubozu
'CDLCONCEALBABYSWALL', # Concealing Baby Swallow
'CDLCOUNTERATTACK', # Counterattack
'CDLDARKCLOUDCOVER', # Dark Cloud Cover
'CDLDOJI', # Doji
'CDLDOJISTAR', # Doji Star
'CDLDRAGONFLYDOJI', # Dragonfly Doji
'CDLENGULFING', # Engulfing Pattern
'CDLEVENINGDOJISTAR', # Evening Doji Star
'CDLEVENINGSTAR', # Evening Star
'CDLGAPSIDESIDEWHITE', # Up/Down-gap side-by-side white lines
'CDLGRAVESTONEDOJI', # Gravestone Doji
'CDLHAMMER', # Hammer
'CDLHANGINGMAN', # Hanging Man
'CDLHARAMI', # Harami Pattern
'CDLHARAMICROSS', # Harami Cross Pattern
'CDLHIGHWAVE', # High-Wave Candle
'CDLHIKKAKE', # Hikkake Pattern
'CDLHIKKAKEMOD', # Modified Hikkake Pattern
'CDLHOMINGPIGEON', # Homing Pigeon
'CDLIDENTICAL3CROWS', # Identical Three Crows
'CDLINNECK', # In-Neck Pattern
'CDLINVERTEDHAMMER', # Inverted Hammer
'CDLKICKING', # Kicking
'CDLKICKINGBYLENGTH', # Kicking - bull/bear determined by the longer marubozu
'CDLLADDERBOTTOM', # Ladder Bottom
'CDLLONGLEGGEDDOJI', # Long Legged Doji
'CDLLONGLINE', # Long Line Candle
'CDLMARUBOZU', # Marubozu
'CDLMATCHINGLOW', # Matching Low
'CDLMATHOLD', # Mat Hold
'CDLMORNINGDOJISTAR', # Morning Doji Star
'CDLMORNINGSTAR', # Morning Star
'CDLONNECK', # On-Neck Pattern
'CDLPIERCING', # Piercing Pattern
'CDLRICKSHAWMAN', # Rickshaw Man
'CDLRISEFALL3METHODS', # Rising/Falling Three Methods
'CDLSEPARATINGLINES', # Separating Lines
'CDLSHOOTINGSTAR', # Shooting Star
'CDLSHORTLINE', # Short Line Candle
'CDLSPINNINGTOP', # Spinning Top
'CDLSTALLEDPATTERN', # Stalled Pattern
'CDLSTICKSANDWICH', # Stick Sandwich
# Takuri (Dragonfly Doji with very long lower shadow)
'CDLTAKURI',
'CDLTASUKIGAP', # Tasuki Gap
'CDLTHRUSTING', # Thrusting Pattern
'CDLTRISTAR', # Tristar Pattern
'CDLUNIQUE3RIVER', # Unique 3 River
'CDLUPSIDEGAP2CROWS', # Upside Gap Two Crows
'CDLXSIDEGAP3METHODS', # Upside/Downside Gap Three Methods
},
'Statistic Functions': {
'BETA', # Beta
'CORREL', # Pearson's Correlation Coefficient (r)
'LINEARREG', # Linear Regression
'LINEARREG_ANGLE', # Linear Regression Angle
'LINEARREG_INTERCEPT', # Linear Regression Intercept
'LINEARREG_SLOPE', # Linear Regression Slope
'STDDEV', # Standard Deviation
'TSF', # Time Series Forecast
'VAR', # Variance
}
}
god_genes = set()
########################### SETTINGS ##############################
# god_genes = {'SMA'}
god_genes |= all_god_genes['Overlap Studies']
god_genes |= all_god_genes['Momentum Indicators']
god_genes |= all_god_genes['Volume Indicators']
god_genes |= all_god_genes['Volatility Indicators']
god_genes |= all_god_genes['Price Transform']
god_genes |= all_god_genes['Cycle Indicators']
god_genes |= all_god_genes['Pattern Recognition']
god_genes |= all_god_genes['Statistic Functions']
timeperiods = [5, 6, 12, 15, 50, 55, 100, 110]
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 = 1
########################### END SETTINGS ##########################
# DATAFRAME = DataFrame()
god_genes = list(god_genes)
# print('selected indicators for optimzatin: \n', god_genes)
god_genes_with_timeperiod = list()
for god_gene in god_genes:
for timeperiod in timeperiods:
god_genes_with_timeperiod.append(f'{god_gene}-{timeperiod}')
# Let give somethings to CatagoricalParam to Play with them
# When just one thing is inside catagorical lists
# TODO: its Not True Way :)
if len(god_genes) == 1:
god_genes = god_genes*2
if len(timeperiods) == 1:
timeperiods = timeperiods*2
if len(operators) == 1:
operators = operators*2
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):
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] > dataframe[crossed_indicator]
)
elif operator == "=":
condition = (
np.isclose(dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "<":
condition = (
dataframe[indicator] < dataframe[crossed_indicator]
)
elif operator == "C":
condition = (
(qtpylib.crossed_below(dataframe[indicator], dataframe[crossed_indicator])) |
(qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator]))
)
elif operator == "CA":
condition = (
qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "CB":
condition = (
qtpylib.crossed_below(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == ">R":
condition = (
dataframe[indicator] > real_num
)
elif operator == "=R":
condition = (
np.isclose(dataframe[indicator], real_num)
)
elif operator == "<R":
condition = (
dataframe[indicator] < real_num
)
elif operator == "/>R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) > real_num
)
elif operator == "/=R":
condition = (
np.isclose(dataframe[indicator].div(
dataframe[crossed_indicator]), real_num)
)
elif operator == "/<R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) < real_num
)
elif operator == "UT":
condition = (
dataframe[indicator] > dataframe[indicator_trend_sma]
)
elif operator == "DT":
condition = (
dataframe[indicator] < dataframe[indicator_trend_sma]
)
elif operator == "OT":
condition = (
np.isclose(dataframe[indicator], dataframe[indicator_trend_sma])
)
elif operator == "CUT":
condition = (
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] > dataframe[indicator_trend_sma]
)
)
elif operator == "CDT":
condition = (
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] < dataframe[indicator_trend_sma]
)
)
elif operator == "COT":
condition = (
(
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) |
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
) &
(
np.isclose(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
)
return condition, dataframe
class GodStraJD3(IStrategy):
# #################### RESULTS PASTE PLACE ####################
# ROI table:
minimal_roi = {
"0": 0.598,
"644": 0.166,
"3269": 0.115,
"7289": 0
}
# Stoploss:
stoploss = -0.128
# Buy hypers
timeframe = '4h'
# Trailing stoploss
trailing_stop = True
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': 'white'},
'bb_upperband': {'color': 'white'},
},
'subplots': {
# Subplots - each dict defines one additional plot
"BB": {
'bbwitth': {'color': 'blue'},
}
}
}
# #################### END OF RESULT PLACE ####################
# TODO: Its not dry code!
# Buy Hyperoptable Parameters/Spaces.
buy_crossed_indicator0 = CategoricalParameter(
god_genes_with_timeperiod, default="ADD-20", space='buy')
buy_crossed_indicator1 = CategoricalParameter(
god_genes_with_timeperiod, default="ASIN-6", space='buy')
buy_crossed_indicator2 = CategoricalParameter(
god_genes_with_timeperiod, default="CDLEVENINGSTAR-50", space='buy')
buy_indicator0 = CategoricalParameter(
god_genes_with_timeperiod, default="SMA-100", space='buy')
buy_indicator1 = CategoricalParameter(
god_genes_with_timeperiod, default="WILLR-50", space='buy')
buy_indicator2 = CategoricalParameter(
god_genes_with_timeperiod, default="CDLHANGINGMAN-20", space='buy')
buy_operator0 = CategoricalParameter(operators, default="/<R", space='buy')
buy_operator1 = CategoricalParameter(operators, default="<R", space='buy')
buy_operator2 = CategoricalParameter(operators, default="CB", space='buy')
buy_real_num0 = DecimalParameter(
0, 1, decimals=DECIMALS, default=0.89009, space='buy')
buy_real_num1 = DecimalParameter(
0, 1, decimals=DECIMALS, default=0.56953, space='buy')
buy_real_num2 = DecimalParameter(
0, 1, decimals=DECIMALS, default=0.38365, space='buy')
# Sell Hyperoptable Parameters/Spaces.
sell_crossed_indicator0 = CategoricalParameter(
god_genes_with_timeperiod, default="CDLSHOOTINGSTAR-150", space='sell')
sell_crossed_indicator1 = CategoricalParameter(
god_genes_with_timeperiod, default="MAMA-1-100", space='sell')
sell_crossed_indicator2 = CategoricalParameter(
god_genes_with_timeperiod, default="CDLMATHOLD-6", space='sell')
sell_indicator0 = CategoricalParameter(
god_genes_with_timeperiod, default="CDLUPSIDEGAP2CROWS-5", space='sell')
sell_indicator1 = CategoricalParameter(
god_genes_with_timeperiod, default="CDLHARAMICROSS-150", space='sell')
sell_indicator2 = CategoricalParameter(
god_genes_with_timeperiod, default="CDL2CROWS-5", space='sell')
sell_operator0 = CategoricalParameter(
operators, default="<R", space='sell')
sell_operator1 = CategoricalParameter(operators, default="D", space='sell')
sell_operator2 = CategoricalParameter(
operators, default="/>R", space='sell')
sell_real_num0 = DecimalParameter(
0, 1, decimals=DECIMALS, default=0.09731, space='sell')
sell_real_num1 = DecimalParameter(
0, 1, decimals=DECIMALS, default=0.81657, space='sell')
sell_real_num2 = DecimalParameter(
0, 1, decimals=DECIMALS, default=0.87267, space='sell')
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
'''
It's good to calculate all indicators in all time periods here and so optimize the strategy.
But this strategy can take much time to generate anything that may not use in his optimization.
I just calculate the specific indicators in specific time period inside buy and sell strategy populator methods if needed.
Also, this method (populate_indicators) just calculates default value of hyperoptable params
so using this method have not big benefits instade of calculating useable things inside buy and sell trand populators
'''
# 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"]
)
# 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"]
)
# # EMA - Exponential Moving Average
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = list()
# TODO: Its not dry code!
buy_indicator = self.buy_indicator0.value
buy_crossed_indicator = self.buy_crossed_indicator0.value
buy_operator = self.buy_operator0.value
buy_real_num = self.buy_real_num0.value
condition, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition)
# backup
buy_indicator = self.buy_indicator1.value
buy_crossed_indicator = self.buy_crossed_indicator1.value
buy_operator = self.buy_operator1.value
buy_real_num = self.buy_real_num1.value
condition, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition)
buy_indicator = self.buy_indicator2.value
buy_crossed_indicator = self.buy_crossed_indicator2.value
buy_operator = self.buy_operator2.value
buy_real_num = self.buy_real_num2.value
condition, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition)
if conditions:
dataframe.loc[
(
(dataframe['close'] < dataframe['bb_lowerband'])
& (dataframe['bb_width'] >= 0.12)
& (dataframe['volume'] > 0)
) |
reduce(lambda x, y: x & y, conditions),
'buy']=1
# print(len(dataframe.keys()))
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = list()
# TODO: Its not dry code!
sell_indicator = self.sell_indicator0.value
sell_crossed_indicator = self.sell_crossed_indicator0.value
sell_operator = self.sell_operator0.value
sell_real_num = self.sell_real_num0.value
condition, dataframe = condition_generator(
dataframe,
sell_operator,
sell_indicator,
sell_crossed_indicator,
sell_real_num
)
conditions.append(condition)
sell_indicator = self.sell_indicator1.value
sell_crossed_indicator = self.sell_crossed_indicator1.value
sell_operator = self.sell_operator1.value
sell_real_num = self.sell_real_num1.value
condition, dataframe = condition_generator(
dataframe,
sell_operator,
sell_indicator,
sell_crossed_indicator,
sell_real_num
)
conditions.append(condition)
sell_indicator = self.sell_indicator2.value
sell_crossed_indicator = self.sell_crossed_indicator2.value
sell_operator = self.sell_operator2.value
sell_real_num = self.sell_real_num2.value
condition, dataframe = condition_generator(
dataframe,
sell_operator,
sell_indicator,
sell_crossed_indicator,
sell_real_num
)
conditions.append(condition)
#dataframe.loc[(dataframe['close'] < dataframe['bb_lowerband']),'sell']=1
if conditions:
dataframe.loc[
(
reduce(lambda x, y: x & y, conditions)
),
'sell']=1
return dataframe
class StrategyHelperLocal:
"""
simple helper class to predefine a couple of patterns for our
strategy
"""
@staticmethod
def two_green_candles(dataframe):
"""
evaluates if we are having 7 green candles in a row
:param self:
:param dataframe:
:return:
"""
return (
(dataframe['open'] < dataframe['close']) &
(dataframe['open'].shift(1) < dataframe['close'].shift(1))
# (dataframe['open'].shift(2) < dataframe['close'].shift(2))
)
@staticmethod
def no_more_three_green_candles(dataframe):
"""
evaluates if we are having not more than 3 green candles in a row
:param self:
:param dataframe:
:return:
"""
return not (
(dataframe['open'] < dataframe['close']) &
(dataframe['open'].shift(1) < dataframe['close'].shift(1)) &
(dataframe['open'].shift(2) < dataframe['close'].shift(2)) &
(dataframe['open'].shift(3) < dataframe['close'].shift(3))
)
@staticmethod
def seven_green_candles(dataframe):
"""
evaluates if we are having 7 green candles in a row
:param self:
:param dataframe:
:return:
"""
return (
(dataframe['open'] < dataframe['close']) &
(dataframe['open'].shift(1) < dataframe['close'].shift(1)) &
(dataframe['open'].shift(2) < dataframe['close'].shift(2)) &
(dataframe['open'].shift(3) < dataframe['close'].shift(3)) &
(dataframe['open'].shift(4) < dataframe['close'].shift(4)) &
(dataframe['open'].shift(5) < dataframe['close'].shift(5)) &
(dataframe['open'].shift(6) < dataframe['close'].shift(6)) &
(dataframe['open'].shift(7) < dataframe['close'].shift(7))
)
@staticmethod
def eight_green_candles(dataframe):
"""
evaluates if we are having 8 green candles in a row
:param self:
:param dataframe:
:return:
"""
return (
(dataframe['open'] < dataframe['close']) &
(dataframe['open'].shift(1) < dataframe['close'].shift(1)) &
(dataframe['open'].shift(2) < dataframe['close'].shift(2)) &
(dataframe['open'].shift(3) < dataframe['close'].shift(3)) &
(dataframe['open'].shift(4) < dataframe['close'].shift(4)) &
(dataframe['open'].shift(5) < dataframe['close'].shift(5)) &
(dataframe['open'].shift(6) < dataframe['close'].shift(6)) &
(dataframe['open'].shift(7) < dataframe['close'].shift(7)) &
(dataframe['open'].shift(8) < dataframe['close'].shift(8))
)
@staticmethod
def two_red_candles(dataframe, shift=0):
"""
evaluates if we are having 8 red candles in a row
:param self:
:param dataframe:
:param shift: shift the pattern by n
:return:
"""
return (
(dataframe['open'].shift(shift) > dataframe['close'].shift(shift)) &
(dataframe['open'].shift(1 + shift) > dataframe['close'].shift(1 + shift))
# (dataframe['open'].shift(2 + shift) > dataframe['close'].shift(2 + shift)) &
# (dataframe['open'].shift(5 + shift) > dataframe['close'].shift(5 + shift)) &
# (dataframe['open'].shift(6 + shift) > dataframe['close'].shift(6 + shift)) &
# (dataframe['open'].shift(7 + shift) > dataframe['close'].shift(7 + shift)) &
# (dataframe['open'].shift(8 + shift) > dataframe['close'].shift(8 + shift))
)
@staticmethod
def four_red_candles(dataframe, shift=0):
"""
evaluates if we are having 8 red candles in a row
:param self:
:param dataframe:
:param shift: shift the pattern by n
:return:
"""
return (
(dataframe['open'].shift(shift) > dataframe['close'].shift(shift)) &
(dataframe['open'].shift(1 + shift) > dataframe['close'].shift(1 + shift)) &
(dataframe['open'].shift(2 + shift) > dataframe['close'].shift(2 + shift)) &
(dataframe['open'].shift(3 + shift) > dataframe['close'].shift(3 + shift)) &
(dataframe['open'].shift(4 + shift) > dataframe['close'].shift(4 + shift))
# (dataframe['open'].shift(5 + shift) > dataframe['close'].shift(5 + shift)) &
# (dataframe['open'].shift(6 + shift) > dataframe['close'].shift(6 + shift)) &
# (dataframe['open'].shift(7 + shift) > dataframe['close'].shift(7 + shift)) &
# (dataframe['open'].shift(8 + shift) > dataframe['close'].shift(8 + shift))
)
@staticmethod
def two_green_one_red_candle(dataframe):
"""
evaluates if we are having a red candle and 4 previous green
:param self:
:param dataframe:
:return:
"""
return (
(dataframe['open'] < dataframe['close']) &
(dataframe['open'].shift(1) < dataframe['close'].shift(1)) &
(dataframe['open'].shift(2) > dataframe['close'].shift(2))
)
@staticmethod
def four_green_one_red_candle(dataframe):
"""
evaluates if we are having a red candle and 4 previous green
:param self:
:param dataframe:
:return:
"""
return (
(dataframe['open'] > dataframe['close']) &
(dataframe['open'].shift(1) < dataframe['close'].shift(1)) &
(dataframe['open'].shift(2) < dataframe['close'].shift(2)) &
(dataframe['open'].shift(3) < dataframe['close'].shift(3)) &
(dataframe['open'].shift(4) < dataframe['close'].shift(4))
)
@staticmethod
def four_red_one_green_candle(dataframe):
"""
evaluates if we are having a green candle and 4 previous red
:param self:
:param dataframe:
:return:
"""
return (
(dataframe['open'] < dataframe['close']) &
(dataframe['open'].shift(1) > dataframe['close'].shift(1)) &
(dataframe['open'].shift(2) > dataframe['close'].shift(2)) &
(dataframe['open'].shift(3) > dataframe['close'].shift(3)) &
(dataframe['open'].shift(4) > dataframe['close'].shift(4))
)

51
GodStraJD3_1.json Normal file
View File

@@ -0,0 +1,51 @@
{
"strategy_name": "GodStraJD3_1",
"params": {
"trailing": {
"trailing_stop": true,
"trailing_stop_positive": 0.15,
"trailing_stop_positive_offset": 0.2,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_crossed_indicator0": "CDLINNECK-6",
"buy_crossed_indicator1": "DEMA-12",
"buy_crossed_indicator2": "CDLHAMMER-12",
"buy_indicator0": "CDLXSIDEGAP3METHODS-55",
"buy_indicator1": "HT_DCPERIOD-55",
"buy_indicator2": "LINEARREG_INTERCEPT-6",
"buy_operator0": "=R",
"buy_operator1": ">R",
"buy_operator2": ">R",
"buy_real_num0": 0.0,
"buy_real_num1": 0.1,
"buy_real_num2": 0.3
},
"sell": {
"sell_crossed_indicator0": "AVGPRICE-100",
"sell_crossed_indicator1": "CDLGAPSIDESIDEWHITE-6",
"sell_crossed_indicator2": "PLUS_DI-15",
"sell_indicator0": "BBANDS-2-50",
"sell_indicator1": "PLUS_DM-6",
"sell_indicator2": "MIDPOINT-100",
"sell_operator0": "/=R",
"sell_operator1": "CUT",
"sell_operator2": "CUT",
"sell_real_num0": 0.1,
"sell_real_num1": 0.2,
"sell_real_num2": 1.0
},
"protection": {},
"roi": {
"0": 0.594,
"1344": 0.201,
"3068": 0.081,
"5986": 0
},
"stoploss": {
"stoploss": -0.116
}
},
"ft_stratparam_v": 1,
"export_time": "2022-01-03 05:11:14.667810+00:00"
}

1033
GodStraJD3_1.py Normal file

File diff suppressed because it is too large Load Diff

84
GodStraJD3_2.json Normal file
View File

@@ -0,0 +1,84 @@
{
"strategy_name": "GodStraJD3_2",
"params": {
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.15,
"trailing_stop_positive_offset": 0.2,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_indicator0": "CDLSHOOTINGSTAR-110",
"buy_crossed_indicator0": "CDLTASUKIGAP-5",
"buy_operator0": ">",
"buy_real_num0": 1.0,
"buy_indicator1": "MACDFIX-2-12",
"buy_crossed_indicator1": "CDLSPINNINGTOP-6",
"buy_operator1": "<",
"buy_real_num1": 0.2,
"buy_indicator2": "DEMA-110",
"buy_crossed_indicator2": "CDL3WHITESOLDIERS-110",
"buy_operator2": "/<R",
"buy_real_num2": 0.7
},
"sell": {
"sell_crossed_indicator0": "HT_DCPERIOD-5",
"sell_crossed_indicator1": "HT_PHASOR-1-6",
"sell_crossed_indicator2": "VAR-50",
"sell_indicator0": "CDL3LINESTRIKE-15",
"sell_indicator1": "CDLGAPSIDESIDEWHITE-110",
"sell_indicator2": "CDLHIGHWAVE-12",
"sell_operator0": "=",
"sell_operator1": "DT",
"sell_operator2": "/>R",
"sell_real_num0": 0.9,
"sell_real_num1": 0.6,
"sell_real_num2": 0.3
},
"protections": [
{
"method": "CooldownPeriod",
"stop_duration_candles": 5
},
{
"method": "MaxDrawdown",
"lookback_period_candles": 48,
"trade_limit": 2,
"stop_duration_candles": 100,
"max_allowed_drawdown": 0.1
},
{
"method": "StoplossGuard",
"lookback_period_candles": 24,
"trade_limit": 4,
"stop_duration_candles": 2,
"only_per_pair": false
},
{
"method": "LowProfitPairs",
"lookback_period_candles": 6,
"trade_limit": 2,
"stop_duration_candles": 60,
"required_profit": 0.02
},
{
"method": "LowProfitPairs",
"lookback_period_candles": 24,
"trade_limit": 4,
"stop_duration_candles": 2,
"required_profit": 0.01
}
],
"roi": {
"0": 0.893,
"1606": 0.31,
"4383": 0.122,
"10010": 0
},
"stoploss": {
"stoploss": -1
}
},
"ft_stratparam_v": 1,
"export_time": "2022-01-02 04:52:51.009356+00:00"
}

84
GodStraJD3_2.jsonOLD Normal file
View File

@@ -0,0 +1,84 @@
{
"strategy_name": "GodStraJD3_2",
"params": {
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.15,
"trailing_stop_positive_offset": 0.2,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_indicator0": "CDLSHOOTINGSTAR-110",
"buy_crossed_indicator0": "CDLTASUKIGAP-5",
"buy_operator0": ">",
"buy_real_num0": 1.0,
"buy_indicator1": "MACDFIX-2-12",
"buy_crossed_indicator1": "CDLSPINNINGTOP-6",
"buy_operator1": "<",
"buy_real_num1": 0.2,
"buy_indicator2": "DEMA-110",
"buy_crossed_indicator2": "CDL3WHITESOLDIERS-110",
"buy_operator2": "/<R",
"buy_real_num2": 0.7
},
"sell": {
"sell_crossed_indicator0": "HT_DCPERIOD-5",
"sell_crossed_indicator1": "HT_PHASOR-1-6",
"sell_crossed_indicator2": "VAR-50",
"sell_indicator0": "CDL3LINESTRIKE-15",
"sell_indicator1": "CDLGAPSIDESIDEWHITE-110",
"sell_indicator2": "CDLHIGHWAVE-12",
"sell_operator0": "=",
"sell_operator1": "DT",
"sell_operator2": "/>R",
"sell_real_num0": 0.9,
"sell_real_num1": 0.6,
"sell_real_num2": 0.3
},
"protections": [
{
"method": "CooldownPeriod",
"stop_duration_candles": 5
},
{
"method": "MaxDrawdown",
"lookback_period_candles": 48,
"trade_limit": 2,
"stop_duration_candles": 100,
"max_allowed_drawdown": 0.1
},
{
"method": "StoplossGuard",
"lookback_period_candles": 24,
"trade_limit": 4,
"stop_duration_candles": 2,
"only_per_pair": false
},
{
"method": "LowProfitPairs",
"lookback_period_candles": 6,
"trade_limit": 2,
"stop_duration_candles": 60,
"required_profit": 0.02
},
{
"method": "LowProfitPairs",
"lookback_period_candles": 24,
"trade_limit": 4,
"stop_duration_candles": 2,
"required_profit": 0.01
}
],
"roi": {
"0": 0.893,
"1606": 0.31,
"4383": 0.122,
"10010": 0
},
"stoploss": {
"stoploss": -2
}
},
"ft_stratparam_v": 1,
"export_time": "2022-01-02 04:52:51.009356+00:00"
}

1078
GodStraJD3_2.py Normal file

File diff suppressed because it is too large Load Diff

1111
GodStraJD3_3.py Normal file

File diff suppressed because it is too large Load Diff

41
GodStraJD3_4.json Normal file
View File

@@ -0,0 +1,41 @@
{
"strategy_name": "GodStraJD3_4",
"params": {
"roi": {
"0": 10
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.145,
"trailing_stop_positive_offset": 0.146,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_crossed_indicator0": "T3-10",
"buy_crossed_indicator1": "HT_SINE-1-50",
"buy_crossed_indicator2": "PLUS_DI-20",
"buy_indicator0": "TEMA-50",
"buy_indicator1": "ADXR-50",
"buy_indicator2": "CDLSEPARATINGLINES-50",
"buy_operator0": "/<R",
"buy_operator1": "D",
"buy_operator2": "CA",
"buy_real_num0": 0.68,
"buy_real_num1": 0.38,
"buy_real_num2": 1.0
},
"sell": {},
"protection": {
"lookback": 151,
"protection_max_allowed_dd": 0.94,
"protection_stop": 58,
"protection_stoploss_stop": 10,
"trade_limit": 1
}
},
"ft_stratparam_v": 1,
"export_time": "2022-03-24 06:01:13.737412+00:00"
}

48
GodStraJD3_4.jsonBest Normal file
View File

@@ -0,0 +1,48 @@
{
"strategy_name": "GodStraJD3_4",
"params": {
"roi": {
"0": 1
},
"stoploss": {
"stoploss": -2.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.15,
"trailing_stop_positive_offset": 0.2,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_crossed_indicator0": "MINUS_DM-5",
"buy_crossed_indicator1": "DX-5",
"buy_crossed_indicator2": "LINEARREG-50",
"buy_indicator0": "MA-20",
"buy_indicator1": "STOCH-1-10",
"buy_indicator2": "CDLDRAGONFLYDOJI-5",
"buy_operator0": "/<R",
"buy_operator1": ">",
"buy_operator2": "/<R",
"buy_real_num0": 0.1,
"buy_real_num1": 0.0,
"buy_real_num2": 0.5
},
"sell": {
"sell_crossed_indicator0": "TRANGE-12",
"sell_crossed_indicator1": "CDLEVENINGDOJISTAR-55",
"sell_crossed_indicator2": "HT_PHASOR-0-15",
"sell_indicator0": "HT_PHASOR-0-15",
"sell_indicator1": "AROON-1-110",
"sell_indicator2": "ADX-6",
"sell_operator0": "<R",
"sell_operator1": "/=R",
"sell_operator2": "/=R",
"sell_real_num0": 0.8,
"sell_real_num1": 0.4,
"sell_real_num2": 0.4
},
"protection": {}
},
"ft_stratparam_v": 1,
"export_time": "2022-01-11 21:45:43.286063+00:00"
}

48
GodStraJD3_4.jsonOld Normal file
View File

@@ -0,0 +1,48 @@
{
"strategy_name": "GodStraJD3_4",
"params": {
"roi": {
"0": 1
},
"stoploss": {
"stoploss": -2.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.15,
"trailing_stop_positive_offset": 0.2,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_crossed_indicator0": "MIDPOINT-6",
"buy_crossed_indicator1": "ROCR-5",
"buy_crossed_indicator2": "CDLHARAMI-100",
"buy_indicator0": "WCLPRICE-6",
"buy_indicator1": "AVGPRICE-100",
"buy_indicator2": "CDL3OUTSIDE-15",
"buy_operator0": ">R",
"buy_operator1": "<",
"buy_operator2": "CA",
"buy_real_num0": 0.0,
"buy_real_num1": 0.8,
"buy_real_num2": 0.5
},
"sell": {
"sell_crossed_indicator0": "TRANGE-12",
"sell_crossed_indicator1": "CDLEVENINGDOJISTAR-55",
"sell_crossed_indicator2": "HT_PHASOR-0-15",
"sell_indicator0": "HT_PHASOR-0-15",
"sell_indicator1": "AROON-1-110",
"sell_indicator2": "ADX-6",
"sell_operator0": "<R",
"sell_operator1": "/=R",
"sell_operator2": "/=R",
"sell_real_num0": 0.8,
"sell_real_num1": 0.4,
"sell_real_num2": 0.4
},
"protection": {}
},
"ft_stratparam_v": 1,
"export_time": "2022-01-10 03:09:19.259745+00:00"
}

985
GodStraJD3_4.py Normal file
View File

@@ -0,0 +1,985 @@
# 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 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
from pandas import DataFrame
import time
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
# TODO: this gene is removed 'MAVP' cuz or error on periods
all_god_genes = {
'Overlap Studies': {
'BBANDS-0', # Bollinger Bands
'BBANDS-1', # Bollinger Bands
'BBANDS-2', # Bollinger Bands
'DEMA', # Double Exponential Moving Average
'EMA', # Exponential Moving Average
'HT_TRENDLINE', # Hilbert Transform - Instantaneous Trendline
'KAMA', # Kaufman Adaptive Moving Average
'MA', # Moving average
'MAMA-0', # MESA Adaptive Moving Average
'MAMA-1', # MESA Adaptive Moving Average
# TODO: Fix this
# 'MAVP', # Moving average with variable period
'MIDPOINT', # MidPoint over period
'MIDPRICE', # Midpoint Price over period
'SAR', # Parabolic SAR
'SAREXT', # Parabolic SAR - Extended
'SMA', # Simple Moving Average
'T3', # Triple Exponential Moving Average (T3)
'TEMA', # Triple Exponential Moving Average
'TRIMA', # Triangular Moving Average
'WMA', # Weighted Moving Average
},
'Momentum Indicators': {
'ADX', # Average Directional Movement Index
'ADXR', # Average Directional Movement Index Rating
'APO', # Absolute Price Oscillator
'AROON-0', # Aroon
'AROON-1', # Aroon
'AROONOSC', # Aroon Oscillator
'BOP', # Balance Of Power
'CCI', # Commodity Channel Index
'CMO', # Chande Momentum Oscillator
'DX', # Directional Movement Index
'MACD-0', # Moving Average Convergence/Divergence
'MACD-1', # Moving Average Convergence/Divergence
'MACD-2', # Moving Average Convergence/Divergence
'MACDEXT-0', # MACD with controllable MA type
'MACDEXT-1', # MACD with controllable MA type
'MACDEXT-2', # MACD with controllable MA type
'MACDFIX-0', # Moving Average Convergence/Divergence Fix 12/26
'MACDFIX-1', # Moving Average Convergence/Divergence Fix 12/26
'MACDFIX-2', # Moving Average Convergence/Divergence Fix 12/26
'MFI', # Money Flow Index
'MINUS_DI', # Minus Directional Indicator
'MINUS_DM', # Minus Directional Movement
'MOM', # Momentum
'PLUS_DI', # Plus Directional Indicator
'PLUS_DM', # Plus Directional Movement
'PPO', # Percentage Price Oscillator
'ROC', # Rate of change : ((price/prevPrice)-1)*100
# Rate of change Percentage: (price-prevPrice)/prevPrice
'ROCP',
'ROCR', # Rate of change ratio: (price/prevPrice)
# Rate of change ratio 100 scale: (price/prevPrice)*100
'ROCR100',
'RSI', # Relative Strength Index
'STOCH-0', # Stochastic
'STOCH-1', # Stochastic
'STOCHF-0', # Stochastic Fast
'STOCHF-1', # Stochastic Fast
'STOCHRSI-0', # Stochastic Relative Strength Index
'STOCHRSI-1', # Stochastic Relative Strength Index
# 1-day Rate-Of-Change (ROC) of a Triple Smooth EMA
'TRIX',
'ULTOSC', # Ultimate Oscillator
'WILLR', # Williams' %R
},
'Volume Indicators': {
'AD', # Chaikin A/D Line
'ADOSC', # Chaikin A/D Oscillator
'OBV', # On Balance Volume
},
'Volatility Indicators': {
'ATR', # Average True Range
'NATR', # Normalized Average True Range
'TRANGE', # True Range
},
'Price Transform': {
'AVGPRICE', # Average Price
'MEDPRICE', # Median Price
'TYPPRICE', # Typical Price
'WCLPRICE', # Weighted Close Price
},
'Cycle Indicators': {
'HT_DCPERIOD', # Hilbert Transform - Dominant Cycle Period
'HT_DCPHASE', # Hilbert Transform - Dominant Cycle Phase
'HT_PHASOR-0', # Hilbert Transform - Phasor Components
'HT_PHASOR-1', # Hilbert Transform - Phasor Components
'HT_SINE-0', # Hilbert Transform - SineWave
'HT_SINE-1', # Hilbert Transform - SineWave
'HT_TRENDMODE', # Hilbert Transform - Trend vs Cycle Mode
},
'Pattern Recognition': {
'CDL2CROWS', # Two Crows
'CDL3BLACKCROWS', # Three Black Crows
'CDL3INSIDE', # Three Inside Up/Down
'CDL3LINESTRIKE', # Three-Line Strike
'CDL3OUTSIDE', # Three Outside Up/Down
'CDL3STARSINSOUTH', # Three Stars In The South
'CDL3WHITESOLDIERS', # Three Advancing White Soldiers
'CDLABANDONEDBABY', # Abandoned Baby
'CDLADVANCEBLOCK', # Advance Block
'CDLBELTHOLD', # Belt-hold
'CDLBREAKAWAY', # Breakaway
'CDLCLOSINGMARUBOZU', # Closing Marubozu
'CDLCONCEALBABYSWALL', # Concealing Baby Swallow
'CDLCOUNTERATTACK', # Counterattack
'CDLDARKCLOUDCOVER', # Dark Cloud Cover
'CDLDOJI', # Doji
'CDLDOJISTAR', # Doji Star
'CDLDRAGONFLYDOJI', # Dragonfly Doji
'CDLENGULFING', # Engulfing Pattern
'CDLEVENINGDOJISTAR', # Evening Doji Star
'CDLEVENINGSTAR', # Evening Star
'CDLGAPSIDESIDEWHITE', # Up/Down-gap side-by-side white lines
'CDLGRAVESTONEDOJI', # Gravestone Doji
'CDLHAMMER', # Hammer
'CDLHANGINGMAN', # Hanging Man
'CDLHARAMI', # Harami Pattern
'CDLHARAMICROSS', # Harami Cross Pattern
'CDLHIGHWAVE', # High-Wave Candle
'CDLHIKKAKE', # Hikkake Pattern
'CDLHIKKAKEMOD', # Modified Hikkake Pattern
'CDLHOMINGPIGEON', # Homing Pigeon
'CDLIDENTICAL3CROWS', # Identical Three Crows
'CDLINNECK', # In-Neck Pattern
'CDLINVERTEDHAMMER', # Inverted Hammer
'CDLKICKING', # Kicking
'CDLKICKINGBYLENGTH', # Kicking - bull/bear determined by the longer marubozu
'CDLLADDERBOTTOM', # Ladder Bottom
'CDLLONGLEGGEDDOJI', # Long Legged Doji
'CDLLONGLINE', # Long Line Candle
'CDLMARUBOZU', # Marubozu
'CDLMATCHINGLOW', # Matching Low
'CDLMATHOLD', # Mat Hold
'CDLMORNINGDOJISTAR', # Morning Doji Star
'CDLMORNINGSTAR', # Morning Star
'CDLONNECK', # On-Neck Pattern
'CDLPIERCING', # Piercing Pattern
'CDLRICKSHAWMAN', # Rickshaw Man
'CDLRISEFALL3METHODS', # Rising/Falling Three Methods
'CDLSEPARATINGLINES', # Separating Lines
'CDLSHOOTINGSTAR', # Shooting Star
'CDLSHORTLINE', # Short Line Candle
'CDLSPINNINGTOP', # Spinning Top
'CDLSTALLEDPATTERN', # Stalled Pattern
'CDLSTICKSANDWICH', # Stick Sandwich
# Takuri (Dragonfly Doji with very long lower shadow)
'CDLTAKURI',
'CDLTASUKIGAP', # Tasuki Gap
'CDLTHRUSTING', # Thrusting Pattern
'CDLTRISTAR', # Tristar Pattern
'CDLUNIQUE3RIVER', # Unique 3 River
'CDLUPSIDEGAP2CROWS', # Upside Gap Two Crows
'CDLXSIDEGAP3METHODS', # Upside/Downside Gap Three Methods
},
'Statistic Functions': {
'BETA', # Beta
'CORREL', # Pearson's Correlation Coefficient (r)
'LINEARREG', # Linear Regression
'LINEARREG_ANGLE', # Linear Regression Angle
'LINEARREG_INTERCEPT', # Linear Regression Intercept
'LINEARREG_SLOPE', # Linear Regression Slope
'STDDEV', # Standard Deviation
'TSF', # Time Series Forecast
'VAR', # Variance
}
}
god_genes = set()
########################### SETTINGS ##############################
# god_genes = {'SMA'}
god_genes |= all_god_genes['Overlap Studies']
god_genes |= all_god_genes['Momentum Indicators']
god_genes |= all_god_genes['Volume Indicators']
god_genes |= all_god_genes['Volatility Indicators']
god_genes |= all_god_genes['Price Transform']
god_genes |= all_god_genes['Cycle Indicators']
god_genes |= all_god_genes['Pattern Recognition']
god_genes |= all_god_genes['Statistic Functions']
#timeperiods = [5, 6, 12, 15, 50, 55, 100, 110]
timeperiods = [5, 10, 20, 50, 100]
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
########################### END SETTINGS ##########################
# DATAFRAME = DataFrame()
god_genes = list(god_genes)
# print('selected indicators for optimzatin: \n', god_genes)
god_genes_with_timeperiod = list()
for god_gene in god_genes:
for timeperiod in timeperiods:
# print(f'{god_gene}-{timeperiod}')
god_genes_with_timeperiod.append(f'{god_gene}-{timeperiod}')
# Let give somethings to CatagoricalParam to Play with them
# When just one thing is inside catagorical lists
# TODO: its Not True Way :)
if len(god_genes) == 1:
god_genes = god_genes*2
if len(timeperiods) == 1:
timeperiods = timeperiods*2
if len(operators) == 1:
operators = operators*2
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):
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] > dataframe[crossed_indicator]
)
elif operator == "=":
condition = (
np.isclose(dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "<":
condition = (
dataframe[indicator] < dataframe[crossed_indicator]
)
elif operator == "C":
condition = (
(qtpylib.crossed_below(dataframe[indicator], dataframe[crossed_indicator])) |
(qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator]))
)
elif operator == "CA":
condition = (
qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "CB":
condition = (
qtpylib.crossed_below(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == ">R":
condition = (
dataframe[indicator] > real_num
)
elif operator == "=R":
condition = (
np.isclose(dataframe[indicator], real_num)
)
elif operator == "<R":
condition = (
dataframe[indicator] < real_num
)
elif operator == "/>R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) > real_num
)
elif operator == "/=R":
condition = (
np.isclose(dataframe[indicator].div(
dataframe[crossed_indicator]), real_num)
)
elif operator == "/<R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) < real_num
)
elif operator == "UT":
condition = (
dataframe[indicator] > dataframe[indicator_trend_sma]
)
elif operator == "DT":
condition = (
dataframe[indicator] < dataframe[indicator_trend_sma]
)
elif operator == "OT":
condition = (
np.isclose(dataframe[indicator], dataframe[indicator_trend_sma])
)
elif operator == "CUT":
condition = (
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] > dataframe[indicator_trend_sma]
)
)
elif operator == "CDT":
condition = (
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] < dataframe[indicator_trend_sma]
)
)
elif operator == "COT":
condition = (
(
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) |
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
) &
(
np.isclose(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
)
return condition, dataframe
class GodStraJD3_4(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'},
'sma10': {'color': 'yellow'},
# 'min': {'color': 'white'},
# 'max': {'color': 'white'},
'sma20': {'color': 'cyan'}
},
'subplots': {
# Subplots - each dict defines one additional plot
"BB": {
'bb_width': {'color': 'white'},
'bb_min': {'color': 'red'},
},
"Ind": {
"PLUS_DM-20": {'color': 'green'},
"CDLTAKURI-5": {'color': 'blue'}
},
# "Ind2": {
# 'MINUS_DM-5': {'color': 'green'},
# 'DX-5': {'color': 'blue'},
# 'LINEARREG-50': {'color': 'red'}
# },
# "Profit": {
# 'profit': {'color': 'pink'},
# },
"Rsi": {
'rsi': {'color': 'pink'},
},
# "rolling": {
# 'bb_rolling': {'color': '#87e470'},
# "bb_rolling_min": {'color': '#ac3e2a'}
# },
"percent": {
"percent": {'color': 'green'},
"percent3": {'color': 'blue'},
"percent5": {'color': 'red'}
}
}
}
# #################### END OF RESULT PLACE ####################
profit_no_change = False
profit_old_sma10 = False
profit_over_rsi = True
profit_quick_gain = True
profit_quick_gain_3 = True
profit_quick_lost = False
profit_short_loss = False
profit_sma10 = True
profit_sma20 = True
profit_very_old_sma10 = False
# TODO: Its not dry code!
# Buy Hyperoptable Parameters/Spaces.
buy_crossed_indicator0 = CategoricalParameter(god_genes_with_timeperiod, default="ADD-20", space='buy')
buy_crossed_indicator1 = CategoricalParameter(god_genes_with_timeperiod, default="ASIN-6", space='buy')
buy_crossed_indicator2 = CategoricalParameter(god_genes_with_timeperiod, default="CDLEVENINGSTAR-50", space='buy')
buy_indicator0 = CategoricalParameter(god_genes_with_timeperiod, default="SMA-100", space='buy')
buy_indicator1 = CategoricalParameter(god_genes_with_timeperiod, default="WILLR-50", space='buy')
buy_indicator2 = CategoricalParameter(god_genes_with_timeperiod, default="CDLHANGINGMAN-20", space='buy')
buy_operator0 = CategoricalParameter(operators, default="/<R", space='buy')
buy_operator1 = CategoricalParameter(operators, default="<R", space='buy')
buy_operator2 = CategoricalParameter(operators, default="CB", space='buy')
buy_real_num0 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.89009, space='buy')
buy_real_num1 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.56953, space='buy')
buy_real_num2 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.38365, space='buy')
# buy_shift_bb_lowerband = IntParameter(0, 10, default=2, space='buy')
# Sell Hyperoptable Parameters/Spaces.
# sell_crossed_indicator0 = CategoricalParameter(god_genes_with_timeperiod, default="CDLSHOOTINGSTAR-150", space='sell')
# sell_crossed_indicator1 = CategoricalParameter(god_genes_with_timeperiod, default="MAMA-1-100", space='sell')
# sell_crossed_indicator2 = CategoricalParameter(god_genes_with_timeperiod, default="CDLMATHOLD-6", space='sell')
#
# sell_indicator0 = CategoricalParameter(god_genes_with_timeperiod, default="CDLUPSIDEGAP2CROWS-5", space='sell')
# sell_indicator1 = CategoricalParameter(god_genes_with_timeperiod, default="CDLHARAMICROSS-150", space='sell')
# sell_indicator2 = CategoricalParameter(god_genes_with_timeperiod, default="CDL2CROWS-5", space='sell')
#
# sell_operator0 = CategoricalParameter(operators, default="<R", space='sell')
# sell_operator1 = CategoricalParameter(operators, default="D", space='sell')
# sell_operator2 = CategoricalParameter(operators, default="/>R", space='sell')
#
# sell_real_num0 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.09731, space='sell')
# sell_real_num1 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.81657, space='sell')
# sell_real_num2 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.87267, space='sell')
protection_max_allowed_dd = DecimalParameter(0, 1, decimals=DECIMALS, default=0.04, space='protection')
protection_stop = IntParameter(0, 100, default=48, space='protection')
protection_stoploss_stop = IntParameter(0, 100, default=48, space='protection')
lookback = IntParameter(0, 200, default=48, space='protection')
trade_limit = IntParameter(0, 10, default=2, space='protection')
# buy_cond1_num0 = DecimalParameter(0, 10, decimals=DECIMALS, default=1, space='buy')
#buy_cond1_num1 = DecimalParameter(0, 10, decimals=DECIMALS, default=2, space='buy')
# buy_bbwidth_num0 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.035, space='buy')
#buy_bbwidth_num1 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.055, space='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": "StoplossGuard",
# "lookback_period_candles": 24,
# "trade_limit": 4,
# "stop_duration_candles": 2,
# "only_per_pair": False
# },
# {
# "method": "LowProfitPairs",
# "lookback_period_candles": 6,
# "trade_limit": 2,
# "stop_duration_candles": 60,
# "required_profit": 0.02
# },
# {
# "method": "LowProfitPairs",
# "lookback_period_candles": 24,
# "trade_limit": 4,
# "stop_duration_candles": 2,
# "required_profit": 0.01
# }
]
# def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
# proposed_stake: float, min_stake: float, max_stake: float,
# **kwargs) -> float:
#
# dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
# current_candle = dataframe.iloc[-1].squeeze()
#
# # print("proposed_stake=", proposed_stake, " max_stake=", max_stake)
# if current_candle['bb_width'] > 0.065:
# # print("use more stake", pair, " ", proposed_stake * 2)
# return min(max_stake, proposed_stake * 2)
#
# if current_candle['bb_width'] > 0.045:
# # print("use more stake", pair, " ", proposed_stake * 1.5)
# return min(max_stake, proposed_stake * 1.5)
#
# # if current_candle['bb_width'] < 0.020:
# # print("use less stake", pair, " ", proposed_stake / 2)
# # return min(max_stake, proposed_stake / 2)
# # if self.config['stake_amount'] == 'unlimited':
# # # Use entire available wallet during favorable conditions when in compounding mode.
# # return max_stake
# # else:
# # # Compound profits during favorable conditions instead of using a static stake.
# # return self.wallets.get_total_stake_amount() / self.config['max_open_trades']
#
# # Use default stake amount.
# return proposed_stake
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 >= -0.01) & ((current_time - trade.open_date_utc).days >= 5)\
& ((current_time - trade.open_date_utc).days < 10)\
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
return "too_old_0.01"
if (current_profit >= -0.02) & ((current_time - trade.open_date_utc).days >= 10)\
& ((current_time - trade.open_date_utc).days < 15) \
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
return "too_old_0.02"
if (current_profit >= -0.03) & ((current_time - trade.open_date_utc).days >= 15) \
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
return "too_old_0.03"
if self.profit_quick_lost:
if (current_profit >= 0) & (last_candle['percent3'] < -0.015):
return "quick_lost"
if self.profit_no_change:
if (current_profit > 0.005) & (last_candle['percent10'] < 0.001) & (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 > 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_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'] > 88): # & (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'] > 82) & (last_candle['percent'] < -0.02): #| (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, "4h") 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 += [("ETH/USDT", "5m"), ("BTC/TUSD", "15m")]
return informative_pairs
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# MACD
# macd = ta.MACD(dataframe)
# dataframe['macd'] = macd['macd']
# dataframe['macdsignal'] = macd['macdsignal']
# dataframe['macdhist'] = macd['macdhist']
# # # Plus Directional Indicator / Movement
# dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
# dataframe['plus_di'] = ta.PLUS_DI(dataframe)
#
# # Minus Directional Indicator / Movement
# dataframe['adx'] = ta.ADX(dataframe)
dataframe[self.buy_indicator0.value] = gene_calculator(dataframe, self.buy_indicator0.value)
dataframe[self.buy_crossed_indicator0.value] = gene_calculator(dataframe, self.buy_crossed_indicator0.value)
dataframe[self.buy_indicator1.value] = gene_calculator(dataframe, self.buy_indicator1.value)
dataframe[self.buy_crossed_indicator1.value] = gene_calculator(dataframe, self.buy_crossed_indicator1.value)
# dataframe[self.buy_indicator2.value] = gene_calculator(dataframe, self.buy_indicator2.value)
# dataframe[self.buy_crossed_indicator2.value] = gene_calculator(dataframe, self.buy_crossed_indicator2.value)
# dataframe['MINUS_DM-5'] = ta.MINUS_DM(dataframe, timeperiod=5)
# dataframe['LINEARREG-50'] = ta.LINEARREG(dataframe, timeperiod=50)
# dataframe['MA-20'] = ta.MA(dataframe, timeperiod=20)
# stoch = ta.STOCH(dataframe, timeperiod=10)
# # print(stoch)
# dataframe['STOCH-1-10'] = stoch['slowd']
# dataframe['CDLDRAGONFLYDOJI-5'] = ta.CDLDRAGONFLYDOJI(dataframe, timeperiod=5)
# dataframe['minus_di'] = ta.MINUS_DI(dataframe)
# dataframe['min'] = ta.MIN(dataframe)
# dataframe['max'] = ta.MAX(dataframe)
# # Aroon, Aroon Oscillator
# aroon = ta.AROON(dataframe)
# dataframe['aroonup'] = aroon['aroonup']
# dataframe['aroondown'] = aroon['aroondown']
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
dataframe['profit'] = 0
# RSI
dataframe['rsi'] = ta.RSI(dataframe)
# # EMA - Exponential Moving Average
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
# dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
# # SMA - Simple Moving Average
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
# 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['sma200'] = ta.SMA(dataframe, timeperiod=200)
# dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
# dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
# dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
dataframe["percent"] = (dataframe["close"] - dataframe["open"]) / dataframe["open"]
# dataframe["sum_percent"] = dataframe["sum_percent"].shift(1) + dataframe["percent"]
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['min'] = ta.MIN(dataframe['close'], timeperiod=200)
dataframe['min20'] = ta.MIN(dataframe['close'], timeperiod=20)
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_min'] = ta.MIN(dataframe['bb_lowerband'], timeperiod=36)
# 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"]
)
# # 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="4h")
informative["percent"] = (informative["close"] - informative["open"]) / informative["open"]
informative["percent5"] = informative["percent"].rolling(5).sum()
informative["percent3"] = informative["percent"].rolling(3).sum()
# 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["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:
conditions = list()
# TODO: Its not dry code!
buy_indicator = self.buy_indicator0.value
buy_crossed_indicator = self.buy_crossed_indicator0.value
buy_operator = self.buy_operator0.value
buy_real_num = self.buy_real_num0.value
condition, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition)
# backup
buy_indicator = self.buy_indicator1.value
buy_crossed_indicator = self.buy_crossed_indicator1.value
buy_operator = self.buy_operator1.value
buy_real_num = self.buy_real_num1.value
condition, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition)
buy_indicator = self.buy_indicator2.value
buy_crossed_indicator = self.buy_crossed_indicator2.value
buy_operator = self.buy_operator2.value
buy_real_num = self.buy_real_num2.value
condition, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition)
if conditions:
dataframe.loc[
(reduce(lambda x, y: x & y, conditions)
# & (dataframe['percent_4h'] > 0)
& (dataframe['percent3_4h'] <= 0)
),
'buy']=1
# print(len(dataframe.keys()))
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
return dataframe

54
GodStraJD3_4_1.json Normal file
View File

@@ -0,0 +1,54 @@
{
"strategy_name": "GodStraJD3_4_1",
"params": {
"roi": {
"0": 10
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.145,
"trailing_stop_positive_offset": 0.146,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_bbwidth_num0": 0.9,
"buy_cond1_num0": 5.74,
"buy_crossed_indicator0": "CDLIDENTICAL3CROWS-100",
"buy_crossed_indicator1": "CDLMORNINGDOJISTAR-20",
"buy_crossed_indicator2": "CDLEVENINGSTAR-10",
"buy_indicator0": "HT_PHASOR-0-100",
"buy_indicator1": "DEMA-10",
"buy_indicator2": "CDLEVENINGSTAR-10",
"buy_operator0": "/<R",
"buy_operator1": "<R",
"buy_operator2": "D",
"buy_real_num0": 0.91,
"buy_real_num1": 0.55,
"buy_real_num2": 0.19,
"buy_shift_bb_lowerband": 1,
"profit_no_change": false,
"profit_old_sma10": true,
"profit_over_rsi": false,
"profit_quick_gain": false,
"profit_quick_gain_3": false,
"profit_quick_lost": true,
"profit_short_loss": true,
"profit_sma10": true,
"profit_sma20": true,
"profit_very_old_sma10": false
},
"sell": {},
"protection": {
"lookback": 151,
"protection_max_allowed_dd": 0.94,
"protection_stop": 58,
"protection_stoploss_stop": 10,
"trade_limit": 1
}
},
"ft_stratparam_v": 1,
"export_time": "2022-02-07 17:23:41.297535+00:00"
}

1121
GodStraJD3_4_1.py Normal file

File diff suppressed because it is too large Load Diff

26
GodStraJD3_5.json Normal file
View File

@@ -0,0 +1,26 @@
{
"strategy_name": "GodStraJD3_5",
"params": {
"roi": {
"0": 10
},
"stoploss": {
"stoploss": -1
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.15,
"trailing_stop_positive_offset": 0.2,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_real_num0": 0.7,
"buy_real_num1": 0.48,
"buy_real_num2": 0.67
},
"sell": {},
"protection": {}
},
"ft_stratparam_v": 1,
"export_time": "2022-01-14 20:24:56.873912+00:00"
}

618
GodStraJD3_5.py Normal file
View File

@@ -0,0 +1,618 @@
# 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 freqtrade import data
from freqtrade.persistence import Trade
from freqtrade.strategy.parameters import CategoricalParameter, DecimalParameter, IntParameter
from numpy.lib import math
from freqtrade.strategy.interface import IStrategy
import pandas
from pandas import DataFrame
# --------------------------------
# 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
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'
# "buy_real_num0": 0.46,
# "buy_real_num1": 0.48,
# "buy_real_num2": 0.67
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):
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] > dataframe[crossed_indicator]
)
elif operator == "=":
condition = (
np.isclose(dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "<":
condition = (
dataframe[indicator] < dataframe[crossed_indicator]
)
elif operator == "C":
condition = (
(qtpylib.crossed_below(dataframe[indicator], dataframe[crossed_indicator])) |
(qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator]))
)
elif operator == "CA":
condition = (
qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "CB":
condition = (
qtpylib.crossed_below(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == ">R":
condition = (
dataframe[indicator] > real_num
)
elif operator == "=R":
condition = (
np.isclose(dataframe[indicator], real_num)
)
elif operator == "<R":
condition = (
dataframe[indicator] < real_num
)
elif operator == "/>R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) > real_num
)
elif operator == "/=R":
condition = (
np.isclose(dataframe[indicator].div(
dataframe[crossed_indicator]), real_num)
)
elif operator == "/<R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) < real_num
)
elif operator == "UT":
condition = (
dataframe[indicator] > dataframe[indicator_trend_sma]
)
elif operator == "DT":
condition = (
dataframe[indicator] < dataframe[indicator_trend_sma]
)
elif operator == "OT":
condition = (
np.isclose(dataframe[indicator], dataframe[indicator_trend_sma])
)
elif operator == "CUT":
condition = (
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] > dataframe[indicator_trend_sma]
)
)
elif operator == "CDT":
condition = (
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] < dataframe[indicator_trend_sma]
)
)
elif operator == "COT":
condition = (
(
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) |
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
) &
(
np.isclose(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
)
return condition, dataframe
class GodStraJD3_5(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'},
'sma10': {'color': 'yellow'},
# 'min': {'color': 'white'},
# 'max': {'color': 'white'},
'sma20': {'color': 'cyan'}
},
'subplots': {
# Subplots - each dict defines one additional plot
"BB": {
'bb_width': {'color': 'white'},
'bb_min': {'color': 'red'},
},
"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'},
},
# "rolling": {
# 'bb_rolling': {'color': '#87e470'},
# "bb_rolling_min": {'color': '#ac3e2a'}
# },
# "percent": {
# "percent": {'color': 'green'},
# "percent3": {'color': 'blue'},
# "percent5": {'color': 'red'}
# }
}
}
# #################### END OF RESULT PLACE ####################
# TODO: Its not dry code!
# Buy Hyperoptable Parameters/Spaces.
# "buy_real_num0": 0.46,
# "buy_real_num1": 0.48,
# "buy_real_num2": 0.67
#
buy_real_num0 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.46, space='buy')
buy_real_num1 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.48, space='buy')
buy_real_num2 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.67, space='buy')
# protection_max_allowed_dd = DecimalParameter(0, 1, decimals=DECIMALS, default=0.04, space='protection')
# protection_stop = IntParameter(0, 100, default=48, space='protection')
# protection_stoploss_stop = IntParameter(0, 100, default=48, space='protection')
# lookback = IntParameter(0, 200, default=48, space='protection')
# trade_limit = IntParameter(0, 10, default=2, space='protection')
#
# @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
# }
# ]
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 (current_profit >= 0) & (last_candle['percent3'] < -0.01):
return "quick_lost"
if (current_profit > 0.005) & (last_candle['percent10'] < 0.001):
return "no_change"
#if (current_profit > 0.01) & (last_candle['rsi'] < 30):
# return "small_rsi"
if (current_profit >= 0.03) & (last_candle['percent3'] < 0) & ((current_time - trade.open_date_utc).seconds <= 3600):
return "quick_gain_3"
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.01) \
& ((previous_5_candle['sma10'] > last_candle['sma10'] * 1.005) \
| (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 (current_profit > 0.005) & (last_candle['percent5'] < 0) \
& ((current_time - trade.open_date_utc).seconds >= 3600) \
& ((previous_last_candle['sma20'] > last_candle['sma20']) &
((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 (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 (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 (current_profit > 0) \
& (last_candle['rsi'] > 88): #| (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.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):
return []
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe['profit'] = 0
# RSI
dataframe['rsi'] = ta.RSI(dataframe)
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['min'] = ta.MIN(dataframe['close'], timeperiod=200)
dataframe['min20'] = ta.MIN(dataframe['close'], timeperiod=20)
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_min'] = ta.MIN(dataframe['bb_lowerband'], timeperiod=36)
# 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["q_0.1"] = dataframe.quantile(.1)
dataframe["q_0.25"] = dataframe.quantile(.25)
dataframe["q_0.33"] = dataframe.quantile(.33)
# # EMA - Exponential Moving Average
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = list()
condition1, dataframe = condition_generator(
dataframe,
buy_operator0,
buy_indicator0,
buy_crossed_indicator0,
self.buy_real_num0.value
)
conditions.append(condition1)
# # backup
# condition2, dataframe = condition_generator(
# dataframe,
# buy_operator1,
# buy_indicator1,
# buy_crossed_indicator1,
# self.buy_real_num1.value
# )
# conditions.append(condition2)
#
# condition3, dataframe = condition_generator(
# dataframe,
# buy_operator2,
# buy_indicator2,
# buy_crossed_indicator2,
# self.buy_real_num2.value
# )
# conditions.append(condition3)
if conditions:
dataframe.loc[
(
reduce(lambda x, y: x & y, conditions)
& (dataframe['volume10'] * dataframe['close'] / 1000 >= 10)
& (dataframe['close'] < dataframe['sma10'])
& (dataframe['open'] < dataframe['sma10'])
& (dataframe['low'] < dataframe['min20'])
& (dataframe['bb_width'] > 0.035)
# ) | (
# (dataframe['volume10'] * dataframe['close'] / 1000 >= 10)
# & (dataframe['percent20'] < -0.01)
# & (dataframe['percent3'] > 0)
# & (dataframe['close'] < dataframe['sma10'])
# & (dataframe['sma100'].shift(1) < dataframe['sma100'])
#
# ) | (
# (dataframe['volume10'].shift(1) * dataframe['close'].shift(1) / 1000 >= 10)
# & (dataframe['percent20'].shift(1) < -0.01)
# & (dataframe['percent3'].shift(1) > 0)
# & (dataframe['close'].shift(1) < dataframe['sma10'].shift(1))
# & (dataframe['sma100'].shift(1) < dataframe['sma100'])
# # & (dataframe['pente5'].shift(1) > 0)
), 'buy'] = 1
pandas.set_option('display.max_rows', dataframe.shape[0] + 1)
pandas.set_option('display.max_columns', 30)
# print(reduce(lambda x, y: x & y, conditions))
# print(reduce(lambda x, y: x & y, condition1), " ",
# reduce(lambda x, y: x & y, condition2), " ",
# reduce(lambda x, y: x & y, condition3), " ",
# # (reduce(lambda x, y: x & y, conditions))
# dataframe['buy'],
#
# )
# if conditions:
# dataframe.loc[
# (
# reduce(lambda x, y: x & y, conditions)
# # & (dataframe['volume10'] * dataframe['close'] / 1000 >= 100)
# # & (dataframe['percent5'] < 0.025)
# # (dataframe['percent10'] < 0.04)
# # ) | (
# # (dataframe['volume10'] * dataframe['close'] / 1000 >= 100)
# # & (dataframe['percent50'] < -0.06)
# # & (dataframe['percent3'] > 0)
# # # & (dataframe['sma10'].shift(12) > dataframe['sma10'].shift(2))
# # & (dataframe['sma10'].shift(2) > dataframe['sma10'].shift(1))
# # & (dataframe['sma10'].shift(1) < dataframe['sma10'])
# # # & (dataframe['sma100'].shift(1) < dataframe['sma100'])
# )
# #(dataframe['percent3'] > 0))
# ,'buy']=1
# print(len(dataframe.keys()))
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
return dataframe

41
GodStraJD3_5_1.json Normal file
View File

@@ -0,0 +1,41 @@
{
"strategy_name": "GodStraJD3_5_1",
"params": {
"roi": {
"0": 10
},
"stoploss": {
"stoploss": -1
},
"buy": {
"buy_real_num0": 0.46,
"buy_real_num1": 0.48,
"buy_real_num2": 0.67,
"profit_no_change": true,
"profit_old_sma10": true,
"profit_over_rsi": true,
"profit_quick_gain": true,
"profit_quick_gain_3": true,
"profit_short_loss": true,
"profit_sma10": true,
"profit_sma20": true,
"profit_very_old_sma10": true
},
"sell": {},
"protection": {
"lookback": 155,
"protection_max_allowed_dd": 0.15,
"protection_stop": 240,
"protection_stoploss_stop": 73,
"trade_limit": 3
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.243,
"trailing_stop_positive_offset": 0.306,
"trailing_only_offset_is_reached": true
}
},
"ft_stratparam_v": 1,
"export_time": "2022-01-29 13:25:27.974545+00:00"
}

View File

@@ -0,0 +1,32 @@
{
"strategy_name": "GodStraJD3_5_1",
"params": {
"roi": {
"0": 10
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.15,
"trailing_stop_positive_offset": 0.2,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_real_num0": 1.0,
"buy_real_num1": 0.11,
"buy_real_num2": 0.47
},
"sell": {},
"protection": {
"lookback": 156,
"protection_max_allowed_dd": 0.56,
"protection_stop": 62,
"protection_stoploss_stop": 46,
"trade_limit": 6
},
"stoploss": {
"stoploss": -0.288
}
},
"ft_stratparam_v": 1,
"export_time": "2022-01-27 20:28:08.774453+00:00"
}

577
GodStraJD3_5_1.py Normal file
View File

@@ -0,0 +1,577 @@
# 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 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
from pandas import DataFrame
# --------------------------------
# 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
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_crossed_indicator1 = 'DX-5'
buy_crossed_indicator2 = 'LINEARREG-50'
buy_indicator0 = 'MA-20'
buy_indicator1 = 'STOCH-1-10'
buy_indicator2 = 'CDLDRAGONFLYDOJI-5'
buy_operator0 = "/<R"
buy_operator1 = ">"
buy_operator2 = "/<R"
# buy_real_num0 = 0.1,
# buy_real_num1 = 0.0,
# buy_real_num2 = 0.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):
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] > dataframe[crossed_indicator]
)
elif operator == "=":
condition = (
np.isclose(dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "<":
condition = (
dataframe[indicator] < dataframe[crossed_indicator]
)
elif operator == "C":
condition = (
(qtpylib.crossed_below(dataframe[indicator], dataframe[crossed_indicator])) |
(qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator]))
)
elif operator == "CA":
condition = (
qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "CB":
condition = (
qtpylib.crossed_below(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == ">R":
condition = (
dataframe[indicator] > real_num
)
elif operator == "=R":
condition = (
np.isclose(dataframe[indicator], real_num)
)
elif operator == "<R":
condition = (
dataframe[indicator] < real_num
)
elif operator == "/>R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) > real_num
)
elif operator == "/=R":
condition = (
np.isclose(dataframe[indicator].div(
dataframe[crossed_indicator]), real_num)
)
elif operator == "/<R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) < real_num
)
elif operator == "UT":
condition = (
dataframe[indicator] > dataframe[indicator_trend_sma]
)
elif operator == "DT":
condition = (
dataframe[indicator] < dataframe[indicator_trend_sma]
)
elif operator == "OT":
condition = (
np.isclose(dataframe[indicator], dataframe[indicator_trend_sma])
)
elif operator == "CUT":
condition = (
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] > dataframe[indicator_trend_sma]
)
)
elif operator == "CDT":
condition = (
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] < dataframe[indicator_trend_sma]
)
)
elif operator == "COT":
condition = (
(
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) |
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
) &
(
np.isclose(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
)
return condition, dataframe
class GodStraJD3_5_1(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'},
'sma10': {'color': 'yellow'},
'min': {'color': 'white'},
'max': {'color': 'white'},
'sma20': {'color': 'cyan'}
},
'subplots': {
# Subplots - each dict defines one additional plot
"BB": {
'bb_width': {'color': 'white'},
'bb_min': {'color': 'red'},
},
"Ind0": {
buy_crossed_indicator0: {'color': 'green'},
buy_indicator0: {'color': 'red'}
},
"Ind1": {
buy_indicator1: {'color': 'yellow'},
buy_crossed_indicator1: {'color': 'pink'}
},
"Ind2": {
buy_indicator2: {'color': 'cyan'},
buy_crossed_indicator2: {'color': 'blue'},
},
"Rsi": {
'rsi': {'color': 'pink'},
},
# "rolling": {
# 'bb_rolling': {'color': '#87e470'},
# "bb_rolling_min": {'color': '#ac3e2a'}
# },
"percent": {
"percent": {'color': 'green'},
"percent3": {'color': 'blue'},
"percent5": {'color': 'red'}
}
}
}
# #################### END OF RESULT PLACE ####################
# TODO: Its not dry code!
# Buy Hyperoptable Parameters/Spaces.
buy_real_num0 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.1, space='buy')
buy_real_num1 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.0, space='buy')
buy_real_num2 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.5, space='buy')
protection_max_allowed_dd = DecimalParameter(0, 1, decimals=DECIMALS, default=0.04, space='protection')
protection_stop = IntParameter(0, 100, default=48, space='protection')
protection_stoploss_stop = IntParameter(0, 100, default=48, space='protection')
lookback = IntParameter(0, 200, default=48, space='protection')
trade_limit = IntParameter(0, 10, default=2, space='protection')
profit_no_change = 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")
@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
}
]
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 self.profit_no_change.value:
if (current_profit > 0.005) & (last_candle['percent10'] < 0.001):
return "no_change"
#if (current_profit > 0.01) & (last_candle['rsi'] < 30):
# return "small_rsi"
if (current_profit >= 0.03) & (last_candle['percent3'] < 0) & ((current_time - trade.open_date_utc).seconds <= 3600):
return "quick_gain_3"
if (0.01 < current_profit < 0.03) & (last_candle['percent3'] < 0): #& ((current_time - trade.open_date_utc).seconds <= 3600)
return "quick_gain"
if self.profit_sma10.value:
if (current_profit > 0.01) \
& ((previous_5_candle['sma10'] > last_candle['sma10'] * 1.005) \
| (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.value:
if (current_profit > 0.005) & (last_candle['percent5'] < 0) \
& ((current_time - trade.open_date_utc).seconds >= 3600) \
& ((previous_last_candle['sma20'] > last_candle['sma20']) &
((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.value:
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.value:
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.value:
if (current_profit > 0) \
& (last_candle['rsi'] > 88): #| (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)):
# print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
return 'over_rsi'
if self.profit_short_loss.value:
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):
return []
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
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['profit'] = 0
# RSI
dataframe['rsi'] = ta.RSI(dataframe)
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['min'] = ta.MIN(dataframe['close'], timeperiod=200)
dataframe['min20'] = ta.MIN(dataframe['close'], timeperiod=20)
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_min'] = ta.MIN(dataframe['bb_lowerband'], timeperiod=36)
# 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"]
)
# # EMA - Exponential Moving Average
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = list()
condition, dataframe = condition_generator(
dataframe,
buy_operator0,
buy_indicator0,
buy_crossed_indicator0,
self.buy_real_num0.value
)
conditions.append(condition)
# backup
condition, dataframe = condition_generator(
dataframe,
buy_operator1,
buy_indicator1,
buy_crossed_indicator1,
self.buy_real_num1.value
)
conditions.append(condition)
condition, dataframe = condition_generator(
dataframe,
buy_operator2,
buy_indicator2,
buy_crossed_indicator2,
self.buy_real_num2.value
)
conditions.append(condition)
if conditions:
dataframe.loc[
(
# reduce(lambda x, y: x & y, conditions)
# & (dataframe['volume10'] * dataframe['close'] / 1000 >= 100)
# # & (dataframe['percent5'] < 0.025)
# # (dataframe['percent10'] < 0.04)
# ) | (
(dataframe['volume10'] * dataframe['close'] / 1000 >= 100)
& ((dataframe['percent20'].shift(5) < -0.025) | (dataframe['percent20'].shift(10) < -0.025))
& ((dataframe['percent5'] > 0.001) | (dataframe['open'] < dataframe['bb_lowerband']))
& (dataframe['sma10'].shift(1) < dataframe['sma10'])
# & (dataframe['open'].shift(50) > dataframe['open'])
)
#(dataframe['percent3'] > 0))
,'buy']=1
# print(len(dataframe.keys()))
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
return dataframe

30
GodStraJD3_5_2.json Normal file
View File

@@ -0,0 +1,30 @@
{
"strategy_name": "GodStraJD3_5_2",
"params": {
"roi": {
"0": 1
},
"stoploss": {
"stoploss": -1
},
"trailing": {
"trailing_stop": true,
"trailing_stop_positive": 0.344,
"trailing_stop_positive_offset": 0.354,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_real_num0": 0.46,
"buy_real_num1": 0.48,
"buy_real_num2": 0.67
},
"sell": {
"sell_real_num0": 0.11,
"sell_real_num1": 0.78,
"sell_real_num2": 0.36
},
"protection": {}
},
"ft_stratparam_v": 1,
"export_time": "2022-01-20 02:01:29.086955+00:00"
}

30
GodStraJD3_5_2.jsonBest Normal file
View File

@@ -0,0 +1,30 @@
{
"strategy_name": "GodStraJD3_5_2",
"params": {
"roi": {
"0": 1
},
"trailing": {
"trailing_stop": true,
"trailing_stop_positive": 0.344,
"trailing_stop_positive_offset": 0.354,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_real_num0": 0.46,
"buy_real_num1": 0.48,
"buy_real_num2": 0.67
},
"sell": {
"sell_real_num0": 0.11,
"sell_real_num1": 0.78,
"sell_real_num2": 0.36
},
"protection": {},
"stoploss": {
"stoploss": -0.02
}
},
"ft_stratparam_v": 1,
"export_time": "2022-01-20 01:13:41.941514+00:00"
}

628
GodStraJD3_5_2.py Normal file
View File

@@ -0,0 +1,628 @@
# 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 freqtrade import data
from freqtrade.persistence import Trade
from freqtrade.strategy.parameters import CategoricalParameter, DecimalParameter, IntParameter
from numpy.lib import math
from freqtrade.strategy.interface import IStrategy
from pandas import DataFrame
# --------------------------------
# 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
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_crossed_indicator1 = 'DX-5'
buy_crossed_indicator2 = 'LINEARREG-50'
buy_indicator0 = 'MA-20'
buy_indicator1 = 'STOCH-1-10'
buy_indicator2 = 'CDLDRAGONFLYDOJI-5'
buy_operator0 = "/<R"
buy_operator1 = ">"
buy_operator2 = "/<R"
sell_crossed_indicator0 = 'MIDPOINT-10'
sell_crossed_indicator1 = 'CDLTRISTAR-10"'
sell_crossed_indicator2 = 'CDLBELTHOLD-50'
sell_indicator0 = 'CDLLONGLINE-20'
sell_indicator1 = 'STOCHF-1-50'
sell_indicator2 = 'MACDEXT-0-5'
sell_operator0 = "<"
sell_operator1 = ">R"
sell_operator2 = ">"
# buy_real_num0 = 0.1,
# buy_real_num1 = 0.0,
# buy_real_num2 = 0.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):
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] > dataframe[crossed_indicator]
)
elif operator == "=":
condition = (
np.isclose(dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "<":
condition = (
dataframe[indicator] < dataframe[crossed_indicator]
)
elif operator == "C":
condition = (
(qtpylib.crossed_below(dataframe[indicator], dataframe[crossed_indicator])) |
(qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator]))
)
elif operator == "CA":
condition = (
qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "CB":
condition = (
qtpylib.crossed_below(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == ">R":
condition = (
dataframe[indicator] > real_num
)
elif operator == "=R":
condition = (
np.isclose(dataframe[indicator], real_num)
)
elif operator == "<R":
condition = (
dataframe[indicator] < real_num
)
elif operator == "/>R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) > real_num
)
elif operator == "/=R":
condition = (
np.isclose(dataframe[indicator].div(
dataframe[crossed_indicator]), real_num)
)
elif operator == "/<R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) < real_num
)
elif operator == "UT":
condition = (
dataframe[indicator] > dataframe[indicator_trend_sma]
)
elif operator == "DT":
condition = (
dataframe[indicator] < dataframe[indicator_trend_sma]
)
elif operator == "OT":
condition = (
np.isclose(dataframe[indicator], dataframe[indicator_trend_sma])
)
elif operator == "CUT":
condition = (
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] > dataframe[indicator_trend_sma]
)
)
elif operator == "CDT":
condition = (
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] < dataframe[indicator_trend_sma]
)
)
elif operator == "COT":
condition = (
(
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) |
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
) &
(
np.isclose(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
)
return condition, dataframe
class GodStraJD3_5_2(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'},
'sma10': {'color': 'yellow'},
'min': {'color': 'white'},
'max': {'color': 'white'},
'sma20': {'color': 'cyan'}
},
'subplots': {
# Subplots - each dict defines one additional plot
"BB": {
'bb_width': {'color': 'white'},
'bb_min': {'color': 'red'},
},
"Ind0": {
buy_crossed_indicator0: {'color': 'green'},
buy_indicator0: {'color': 'red'}
},
"Ind1": {
buy_indicator1: {'color': 'yellow'},
buy_crossed_indicator1: {'color': 'pink'}
},
"Ind2": {
buy_indicator2: {'color': 'cyan'},
buy_crossed_indicator2: {'color': 'blue'},
},
"Sell0": {
sell_crossed_indicator0: {'color': 'green'},
sell_indicator0: {'color': 'red'}
},
"Sell1": {
sell_indicator1: {'color': 'yellow'},
sell_crossed_indicator1: {'color': 'pink'}
},
"Sell2": {
sell_indicator2: {'color': 'cyan'},
sell_crossed_indicator2: {'color': 'blue'},
},
"Rsi": {
'rsi': {'color': 'pink'},
},
# "rolling": {
# 'bb_rolling': {'color': '#87e470'},
# "bb_rolling_min": {'color': '#ac3e2a'}
# },
"percent": {
"percent": {'color': 'green'},
"percent3": {'color': 'blue'},
"percent5": {'color': 'red'}
}
}
}
# #################### END OF RESULT PLACE ####################
# TODO: Its not dry code!
# Buy Hyperoptable Parameters/Spaces.
buy_real_num0 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.1, space='buy')
buy_real_num1 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.0, space='buy')
buy_real_num2 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.5, space='buy')
sell_real_num0 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.09731, space='sell')
sell_real_num1 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.81657, space='sell')
sell_real_num2 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.87267, space='sell')
@property
def protections(self):
return [
{
"method": "CooldownPeriod",
"stop_duration_candles": 12
},
{
"method": "MaxDrawdown",
"lookback_period_candles": 48,
"trade_limit": 2,
"stop_duration_candles": 48,
"max_allowed_drawdown": 0.04,
"only_per_pair": False
},
]
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 (current_profit > 0.015) & (last_candle['percent'] < 0) & ((current_time - trade.open_date_utc).seconds <= 3600):
return "quick_gain"
if (current_profit > 0.01) & (last_candle['rsi'] < 20):
return "small_rsi"
if (current_profit > 0.005) & (last_candle['percent3'] < -0.01):
# print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
return 'quick_lost'
if (current_profit < -0.02) & ((current_time - trade.open_date_utc).seconds >= 3600):
return "stop_loss_1h"
if (current_profit > 0.005) & (last_candle['percent5'] < -0.015):
# print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
return 'very_quick_lost'
# if (current_profit > 0.01) \
# & ((previous_5_candle['sma10'] > last_candle['sma10'] * 1.005) \
# | (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 (current_profit > 0.005) & (last_candle['percent5'] < 0) \
# & ((current_time - trade.open_date_utc).seconds >= 3600) \
# & ((previous_last_candle['sma20'] > last_candle['sma20']) &
# ((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 (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 (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 (current_profit > 0) \
& (previous_last_candle['rsi'] > 88) \
& ((last_candle['percent'] < - current_profit / 3) | (last_candle['percent3'] < - current_profit / 3)):
# print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
return 'over_rsi'
# 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):
return []
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
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[sell_crossed_indicator0] = gene_calculator(dataframe, sell_crossed_indicator0)
dataframe[sell_crossed_indicator1] = gene_calculator(dataframe, sell_crossed_indicator1)
dataframe[sell_crossed_indicator2] = gene_calculator(dataframe, sell_crossed_indicator2)
dataframe[sell_indicator0] = gene_calculator(dataframe, sell_indicator0)
dataframe[sell_indicator1] = gene_calculator(dataframe, sell_indicator1)
dataframe[sell_indicator2] = gene_calculator(dataframe, sell_indicator2)
# RSI
dataframe['rsi'] = ta.RSI(dataframe)
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['min'] = ta.MIN(dataframe['close'], timeperiod=200)
dataframe['min20'] = ta.MIN(dataframe['close'], timeperiod=20)
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_min'] = ta.MIN(dataframe['bb_lowerband'], timeperiod=36)
# 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"]
)
# # EMA - Exponential Moving Average
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = list()
condition, dataframe = condition_generator(
dataframe,
buy_operator0,
buy_indicator0,
buy_crossed_indicator0,
self.buy_real_num0.value
)
conditions.append(condition)
# backup
condition, dataframe = condition_generator(
dataframe,
buy_operator1,
buy_indicator1,
buy_crossed_indicator1,
self.buy_real_num1.value
)
conditions.append(condition)
condition, dataframe = condition_generator(
dataframe,
buy_operator2,
buy_indicator2,
buy_crossed_indicator2,
self.buy_real_num2.value
)
conditions.append(condition)
# condition_1 = (
# reduce(lambda x, y: x & y, conditions) &
# (dataframe['volume10'] * dataframe['close'] / 1000 >= 100) &
# (dataframe['open'] < dataframe['sma20'])
# )
# condition_2 = (
# (dataframe['bb_width'] > 0.11) &
# (dataframe['volume10'] * dataframe['close'] / 1000 >= 100) &
# (dataframe['rsi'].shift(1) < 20) &
# (dataframe['open'] < dataframe['sma20'])
# )
# if (condition_1):
# dataframe.loc[condition_1, 'buy'] = 'buy_opt'
# if (condition_2):
# dataframe.loc[condition_2, 'buy'] = 'bb_width'
if conditions:
dataframe.loc[
(
reduce(lambda x, y: x & y, conditions) &
(dataframe['volume10'] * dataframe['close'] / 1000 >= 100) &
(dataframe['close'] < dataframe['sma20']) &
(dataframe['close'] < dataframe['sma50']) &
(dataframe['close'] * 0.99 < dataframe['bb_lowerband'])
) | (
(dataframe['close'] < dataframe['bb_lowerband']) &
(dataframe['bb_width'] > 0.11) &
(dataframe['volume10'] * dataframe['close'] / 1000 >= 100) &
(dataframe['rsi'] < 30) &
(dataframe['close'] < dataframe['sma20']) &
(dataframe['sma100'].shift(30) < dataframe['sma100'])
),'buy']=1
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = list()
condition, dataframe = condition_generator(
dataframe,
sell_operator0,
sell_indicator0,
sell_crossed_indicator0,
self.sell_real_num0.value
)
conditions.append(condition)
# backup
condition, dataframe = condition_generator(
dataframe,
sell_operator1,
sell_indicator1,
sell_crossed_indicator1,
self.sell_real_num1.value
)
conditions.append(condition)
condition, dataframe = condition_generator(
dataframe,
sell_operator2,
sell_indicator2,
sell_crossed_indicator2,
self.sell_real_num2.value
)
conditions.append(condition)
if conditions:
dataframe.loc[
(
reduce(lambda x, y: x & y, conditions)
),
'sell']=1
return dataframe

29
GodStraJD3_5_3.json Normal file
View File

@@ -0,0 +1,29 @@
{
"strategy_name": "GodStraJD3_5_3",
"params": {
"roi": {
"0": 1
},
"stoploss": {
"stoploss": -0.02
},
"trailing": {
"trailing_stop": true,
"trailing_stop_positive": 0.344,
"trailing_stop_positive_offset": 0.354,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_sma_max": 0.98,
"buy_sma_min": -1.52
},
"sell": {
"sell_real_num0": 0.51,
"sell_real_num1": 0.85,
"sell_real_num2": 0.0
},
"protection": {}
},
"ft_stratparam_v": 1,
"export_time": "2022-01-20 17:43:05.699962+00:00"
}

609
GodStraJD3_5_3.py Normal file
View File

@@ -0,0 +1,609 @@
# 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 freqtrade import data
from freqtrade.persistence import Trade
from freqtrade.strategy.parameters import CategoricalParameter, DecimalParameter, IntParameter
from numpy.lib import math
from freqtrade.strategy.interface import IStrategy
from pandas import DataFrame
# --------------------------------
# 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
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_crossed_indicator1 = 'DX-5'
buy_crossed_indicator2 = 'LINEARREG-50'
buy_indicator0 = 'MA-20'
buy_indicator1 = 'STOCH-1-10'
buy_indicator2 = 'CDLDRAGONFLYDOJI-5'
buy_operator0 = "/<R"
buy_operator1 = ">"
buy_operator2 = "/<R"
sell_crossed_indicator0 = 'MIDPOINT-10'
sell_crossed_indicator1 = 'CDLTRISTAR-10"'
sell_crossed_indicator2 = 'CDLBELTHOLD-50'
sell_indicator0 = 'CDLLONGLINE-20'
sell_indicator1 = 'STOCHF-1-50'
sell_indicator2 = 'MACDEXT-0-5'
sell_operator0 = "<"
sell_operator1 = ">R"
sell_operator2 = ">"
# buy_real_num0 = 0.1,
# buy_real_num1 = 0.0,
# buy_real_num2 = 0.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):
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] > dataframe[crossed_indicator]
)
elif operator == "=":
condition = (
np.isclose(dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "<":
condition = (
dataframe[indicator] < dataframe[crossed_indicator]
)
elif operator == "C":
condition = (
(qtpylib.crossed_below(dataframe[indicator], dataframe[crossed_indicator])) |
(qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator]))
)
elif operator == "CA":
condition = (
qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "CB":
condition = (
qtpylib.crossed_below(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == ">R":
condition = (
dataframe[indicator] > real_num
)
elif operator == "=R":
condition = (
np.isclose(dataframe[indicator], real_num)
)
elif operator == "<R":
condition = (
dataframe[indicator] < real_num
)
elif operator == "/>R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) > real_num
)
elif operator == "/=R":
condition = (
np.isclose(dataframe[indicator].div(
dataframe[crossed_indicator]), real_num)
)
elif operator == "/<R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) < real_num
)
elif operator == "UT":
condition = (
dataframe[indicator] > dataframe[indicator_trend_sma]
)
elif operator == "DT":
condition = (
dataframe[indicator] < dataframe[indicator_trend_sma]
)
elif operator == "OT":
condition = (
np.isclose(dataframe[indicator], dataframe[indicator_trend_sma])
)
elif operator == "CUT":
condition = (
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] > dataframe[indicator_trend_sma]
)
)
elif operator == "CDT":
condition = (
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] < dataframe[indicator_trend_sma]
)
)
elif operator == "COT":
condition = (
(
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) |
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
) &
(
np.isclose(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
)
return condition, dataframe
class GodStraJD3_5_3(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'},
'sma10': {'color': 'yellow'},
'min': {'color': 'white'},
'max': {'color': 'white'},
'sma20': {'color': 'cyan'}
},
'subplots': {
# Subplots - each dict defines one additional plot
"BB": {
'bb_width': {'color': 'white'},
'bb_min': {'color': 'red'},
},
"Ind0": {
buy_crossed_indicator0: {'color': 'green'},
buy_indicator0: {'color': 'red'}
},
"Ind1": {
buy_indicator1: {'color': 'yellow'},
buy_crossed_indicator1: {'color': 'pink'}
},
"Ind2": {
buy_indicator2: {'color': 'cyan'},
buy_crossed_indicator2: {'color': 'blue'},
},
"Sell0": {
sell_crossed_indicator0: {'color': 'green'},
sell_indicator0: {'color': 'red'}
},
"Sell1": {
sell_indicator1: {'color': 'yellow'},
sell_crossed_indicator1: {'color': 'pink'}
},
"Sell2": {
sell_indicator2: {'color': 'cyan'},
sell_crossed_indicator2: {'color': 'blue'},
},
"Rsi": {
'rsi': {'color': 'pink'},
},
# "rolling": {
# 'bb_rolling': {'color': '#87e470'},
# "bb_rolling_min": {'color': '#ac3e2a'}
# },
"percent": {
"percent": {'color': 'green'},
"percent3": {'color': 'blue'},
"percent5": {'color': 'red'}
}
}
}
# #################### END OF RESULT PLACE ####################
# TODO: Its not dry code!
# Buy Hyperoptable Parameters/Spaces.
buy_real_num0 = 0.46
buy_real_num1 = 0.48
buy_real_num2 = 0.67
#buy_real_num0 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.1, space='buy')
#buy_real_num1 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.0, space='buy')
#buy_real_num2 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.5, space='buy')
sell_real_num0 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.09731, space='sell')
sell_real_num1 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.81657, space='sell')
sell_real_num2 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.87267, space='sell')
# buy_bb_width = DecimalParameter(0, 0.2, decimals=3, default=0.12, space='buy')
# buy_bb_min = IntParameter(-30, 50, default=50, space='buy')
buy_sma_min = DecimalParameter(-2, 2, decimals=2, default=0, space='buy')
buy_sma_max = DecimalParameter(-2, 2, decimals=2, default=0.5, space='buy')
@property
def protections(self):
return [
{
"method": "CooldownPeriod",
"stop_duration_candles": 10
},
{
"method": "MaxDrawdown",
"lookback_period_candles": 48,
"trade_limit": 2,
"stop_duration_candles": 72,
"max_allowed_drawdown": 0.04,
"only_per_pair": False
},
]
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 (current_profit > 0.005) & (last_candle['percent10'] < 0.001):
# return "no_change"
if (current_profit > 0.01) & (last_candle['rsi'] < 20):
return "small_rsi"
# if (current_profit > 0.01) \
# & ((previous_5_candle['sma10'] > last_candle['sma10'] * 1.005) \
# | (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 (current_profit > 0.005) & (last_candle['percent5'] < 0) \
# & ((current_time - trade.open_date_utc).seconds >= 3600) \
# & ((previous_last_candle['sma20'] > last_candle['sma20']) &
# ((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 (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 (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 (current_profit > 0) \
& (last_candle['rsi'] > 88): #| (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.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):
return []
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
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[sell_crossed_indicator0] = gene_calculator(dataframe, sell_crossed_indicator0)
dataframe[sell_crossed_indicator1] = gene_calculator(dataframe, sell_crossed_indicator1)
dataframe[sell_crossed_indicator2] = gene_calculator(dataframe, sell_crossed_indicator2)
dataframe[sell_indicator0] = gene_calculator(dataframe, sell_indicator0)
dataframe[sell_indicator1] = gene_calculator(dataframe, sell_indicator1)
dataframe[sell_indicator2] = gene_calculator(dataframe, sell_indicator2)
# RSI
dataframe['rsi'] = ta.RSI(dataframe)
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['min'] = ta.MIN(dataframe['close'], timeperiod=200)
dataframe['min20'] = ta.MIN(dataframe['close'], timeperiod=20)
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_min'] = ta.MIN(dataframe['bb_lowerband'], timeperiod=36)
# 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"]
)
# # EMA - Exponential Moving Average
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = list()
condition, dataframe = condition_generator(
dataframe,
buy_operator0,
buy_indicator0,
buy_crossed_indicator0,
#self.buy_real_num0.value
self.buy_real_num0
)
conditions.append(condition)
# backup
condition, dataframe = condition_generator(
dataframe,
buy_operator1,
buy_indicator1,
buy_crossed_indicator1,
#self.buy_real_num1.value
self.buy_real_num1
)
conditions.append(condition)
condition, dataframe = condition_generator(
dataframe,
buy_operator2,
buy_indicator2,
buy_crossed_indicator2,
#self.buy_real_num2.value
self.buy_real_num2
)
conditions.append(condition)
if conditions:
dataframe.loc[
(
reduce(lambda x, y: x & y, conditions) &
(dataframe['volume10'] * dataframe['close'] / 1000 >= 100) &
# ((100 * ((dataframe['sma100'] - dataframe['sma100'].shift(10)) / dataframe['sma100'])) >= self.buy_sma_min.value) &
# ((100 * ((dataframe['sma100'] - dataframe['sma100'].shift(10)) / dataframe['sma100'])) <= self.buy_sma_max.value) &
(dataframe['close'] < dataframe['sma20'])
),'buy']=1
# print(len(dataframe.keys()))
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = list()
condition, dataframe = condition_generator(
dataframe,
sell_operator0,
sell_indicator0,
sell_crossed_indicator0,
self.sell_real_num0.value
)
conditions.append(condition)
# backup
condition, dataframe = condition_generator(
dataframe,
sell_operator1,
sell_indicator1,
sell_crossed_indicator1,
self.sell_real_num1.value
)
conditions.append(condition)
condition, dataframe = condition_generator(
dataframe,
sell_operator2,
sell_indicator2,
sell_crossed_indicator2,
self.sell_real_num2.value
)
conditions.append(condition)
if conditions:
dataframe.loc[
(
reduce(lambda x, y: x & y, conditions) # (dataframe['open'] < dataframe['sma10'])
),
'sell']=1
return dataframe

48
GodStraJD3_6.json Normal file
View File

@@ -0,0 +1,48 @@
{
"strategy_name": "GodStraJD3_6",
"params": {
"roi": {
"0": 1
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.15,
"trailing_stop_positive_offset": 0.2,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_crossed_indicator0": "CDLTHRUSTING-20",
"buy_crossed_indicator1": "MACDEXT-0-20",
"buy_crossed_indicator2": "CDLXSIDEGAP3METHODS-50",
"buy_indicator0": "MIDPOINT-5",
"buy_indicator1": "RSI-20",
"buy_indicator2": "CDLSHORTLINE-5",
"buy_operator0": "/>R",
"buy_operator1": "<R",
"buy_operator2": "<",
"buy_real_num0": 0.45,
"buy_real_num1": 0.42,
"buy_real_num2": 0.06
},
"sell": {
"sell_crossed_indicator0": "ROCR100-50",
"sell_crossed_indicator1": "SAR-5",
"sell_crossed_indicator2": "STOCH-1-10",
"sell_indicator0": "CDLHAMMER-10",
"sell_indicator1": "MACDFIX-0-10",
"sell_indicator2": "CDLDARKCLOUDCOVER-100",
"sell_operator0": "/<R",
"sell_operator1": ">",
"sell_operator2": "CB",
"sell_real_num0": 0.4,
"sell_real_num1": 0.7,
"sell_real_num2": 0.8
},
"protection": {}
},
"ft_stratparam_v": 1,
"export_time": "2022-01-15 13:33:08.407372+00:00"
}

956
GodStraJD3_6.py Normal file
View File

@@ -0,0 +1,956 @@
# 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 freqtrade import data
from freqtrade.persistence import Trade
from freqtrade.strategy.parameters import CategoricalParameter, DecimalParameter
from numpy.lib import math
from freqtrade.strategy.interface import IStrategy
from pandas import DataFrame
# --------------------------------
# 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
# TODO: this gene is removed 'MAVP' cuz or error on periods
all_god_genes = {
'Overlap Studies': {
'BBANDS-0', # Bollinger Bands
'BBANDS-1', # Bollinger Bands
'BBANDS-2', # Bollinger Bands
'DEMA', # Double Exponential Moving Average
'EMA', # Exponential Moving Average
'HT_TRENDLINE', # Hilbert Transform - Instantaneous Trendline
'KAMA', # Kaufman Adaptive Moving Average
'MA', # Moving average
'MAMA-0', # MESA Adaptive Moving Average
'MAMA-1', # MESA Adaptive Moving Average
# TODO: Fix this
# 'MAVP', # Moving average with variable period
'MIDPOINT', # MidPoint over period
'MIDPRICE', # Midpoint Price over period
'SAR', # Parabolic SAR
'SAREXT', # Parabolic SAR - Extended
'SMA', # Simple Moving Average
'T3', # Triple Exponential Moving Average (T3)
'TEMA', # Triple Exponential Moving Average
'TRIMA', # Triangular Moving Average
'WMA', # Weighted Moving Average
},
'Momentum Indicators': {
'ADX', # Average Directional Movement Index
'ADXR', # Average Directional Movement Index Rating
'APO', # Absolute Price Oscillator
'AROON-0', # Aroon
'AROON-1', # Aroon
'AROONOSC', # Aroon Oscillator
'BOP', # Balance Of Power
'CCI', # Commodity Channel Index
'CMO', # Chande Momentum Oscillator
'DX', # Directional Movement Index
'MACD-0', # Moving Average Convergence/Divergence
'MACD-1', # Moving Average Convergence/Divergence
'MACD-2', # Moving Average Convergence/Divergence
'MACDEXT-0', # MACD with controllable MA type
'MACDEXT-1', # MACD with controllable MA type
'MACDEXT-2', # MACD with controllable MA type
'MACDFIX-0', # Moving Average Convergence/Divergence Fix 12/26
'MACDFIX-1', # Moving Average Convergence/Divergence Fix 12/26
'MACDFIX-2', # Moving Average Convergence/Divergence Fix 12/26
'MFI', # Money Flow Index
'MINUS_DI', # Minus Directional Indicator
'MINUS_DM', # Minus Directional Movement
'MOM', # Momentum
'PLUS_DI', # Plus Directional Indicator
'PLUS_DM', # Plus Directional Movement
'PPO', # Percentage Price Oscillator
'ROC', # Rate of change : ((price/prevPrice)-1)*100
# Rate of change Percentage: (price-prevPrice)/prevPrice
'ROCP',
'ROCR', # Rate of change ratio: (price/prevPrice)
# Rate of change ratio 100 scale: (price/prevPrice)*100
'ROCR100',
'RSI', # Relative Strength Index
'STOCH-0', # Stochastic
'STOCH-1', # Stochastic
'STOCHF-0', # Stochastic Fast
'STOCHF-1', # Stochastic Fast
'STOCHRSI-0', # Stochastic Relative Strength Index
'STOCHRSI-1', # Stochastic Relative Strength Index
# 1-day Rate-Of-Change (ROC) of a Triple Smooth EMA
'TRIX',
'ULTOSC', # Ultimate Oscillator
'WILLR', # Williams' %R
},
'Volume Indicators': {
'AD', # Chaikin A/D Line
'ADOSC', # Chaikin A/D Oscillator
'OBV', # On Balance Volume
},
'Volatility Indicators': {
'ATR', # Average True Range
'NATR', # Normalized Average True Range
'TRANGE', # True Range
},
'Price Transform': {
'AVGPRICE', # Average Price
'MEDPRICE', # Median Price
'TYPPRICE', # Typical Price
'WCLPRICE', # Weighted Close Price
},
'Cycle Indicators': {
'HT_DCPERIOD', # Hilbert Transform - Dominant Cycle Period
'HT_DCPHASE', # Hilbert Transform - Dominant Cycle Phase
'HT_PHASOR-0', # Hilbert Transform - Phasor Components
'HT_PHASOR-1', # Hilbert Transform - Phasor Components
'HT_SINE-0', # Hilbert Transform - SineWave
'HT_SINE-1', # Hilbert Transform - SineWave
'HT_TRENDMODE', # Hilbert Transform - Trend vs Cycle Mode
},
'Pattern Recognition': {
'CDL2CROWS', # Two Crows
'CDL3BLACKCROWS', # Three Black Crows
'CDL3INSIDE', # Three Inside Up/Down
'CDL3LINESTRIKE', # Three-Line Strike
'CDL3OUTSIDE', # Three Outside Up/Down
'CDL3STARSINSOUTH', # Three Stars In The South
'CDL3WHITESOLDIERS', # Three Advancing White Soldiers
'CDLABANDONEDBABY', # Abandoned Baby
'CDLADVANCEBLOCK', # Advance Block
'CDLBELTHOLD', # Belt-hold
'CDLBREAKAWAY', # Breakaway
'CDLCLOSINGMARUBOZU', # Closing Marubozu
'CDLCONCEALBABYSWALL', # Concealing Baby Swallow
'CDLCOUNTERATTACK', # Counterattack
'CDLDARKCLOUDCOVER', # Dark Cloud Cover
'CDLDOJI', # Doji
'CDLDOJISTAR', # Doji Star
'CDLDRAGONFLYDOJI', # Dragonfly Doji
'CDLENGULFING', # Engulfing Pattern
'CDLEVENINGDOJISTAR', # Evening Doji Star
'CDLEVENINGSTAR', # Evening Star
'CDLGAPSIDESIDEWHITE', # Up/Down-gap side-by-side white lines
'CDLGRAVESTONEDOJI', # Gravestone Doji
'CDLHAMMER', # Hammer
'CDLHANGINGMAN', # Hanging Man
'CDLHARAMI', # Harami Pattern
'CDLHARAMICROSS', # Harami Cross Pattern
'CDLHIGHWAVE', # High-Wave Candle
'CDLHIKKAKE', # Hikkake Pattern
'CDLHIKKAKEMOD', # Modified Hikkake Pattern
'CDLHOMINGPIGEON', # Homing Pigeon
'CDLIDENTICAL3CROWS', # Identical Three Crows
'CDLINNECK', # In-Neck Pattern
'CDLINVERTEDHAMMER', # Inverted Hammer
'CDLKICKING', # Kicking
'CDLKICKINGBYLENGTH', # Kicking - bull/bear determined by the longer marubozu
'CDLLADDERBOTTOM', # Ladder Bottom
'CDLLONGLEGGEDDOJI', # Long Legged Doji
'CDLLONGLINE', # Long Line Candle
'CDLMARUBOZU', # Marubozu
'CDLMATCHINGLOW', # Matching Low
'CDLMATHOLD', # Mat Hold
'CDLMORNINGDOJISTAR', # Morning Doji Star
'CDLMORNINGSTAR', # Morning Star
'CDLONNECK', # On-Neck Pattern
'CDLPIERCING', # Piercing Pattern
'CDLRICKSHAWMAN', # Rickshaw Man
'CDLRISEFALL3METHODS', # Rising/Falling Three Methods
'CDLSEPARATINGLINES', # Separating Lines
'CDLSHOOTINGSTAR', # Shooting Star
'CDLSHORTLINE', # Short Line Candle
'CDLSPINNINGTOP', # Spinning Top
'CDLSTALLEDPATTERN', # Stalled Pattern
'CDLSTICKSANDWICH', # Stick Sandwich
# Takuri (Dragonfly Doji with very long lower shadow)
'CDLTAKURI',
'CDLTASUKIGAP', # Tasuki Gap
'CDLTHRUSTING', # Thrusting Pattern
'CDLTRISTAR', # Tristar Pattern
'CDLUNIQUE3RIVER', # Unique 3 River
'CDLUPSIDEGAP2CROWS', # Upside Gap Two Crows
'CDLXSIDEGAP3METHODS', # Upside/Downside Gap Three Methods
},
'Statistic Functions': {
'BETA', # Beta
'CORREL', # Pearson's Correlation Coefficient (r)
'LINEARREG', # Linear Regression
'LINEARREG_ANGLE', # Linear Regression Angle
'LINEARREG_INTERCEPT', # Linear Regression Intercept
'LINEARREG_SLOPE', # Linear Regression Slope
'STDDEV', # Standard Deviation
'TSF', # Time Series Forecast
'VAR', # Variance
}
}
god_genes = set()
########################### SETTINGS ##############################
# god_genes = {'SMA'}
god_genes |= all_god_genes['Overlap Studies']
god_genes |= all_god_genes['Momentum Indicators']
god_genes |= all_god_genes['Volume Indicators']
god_genes |= all_god_genes['Volatility Indicators']
god_genes |= all_god_genes['Price Transform']
god_genes |= all_god_genes['Cycle Indicators']
god_genes |= all_god_genes['Pattern Recognition']
god_genes |= all_god_genes['Statistic Functions']
#timeperiods = [5, 6, 12, 15, 50, 55, 100, 110]
timeperiods = [5, 10, 20, 50, 100]
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
########################### END SETTINGS ##########################
# DATAFRAME = DataFrame()
god_genes = list(god_genes)
# print('selected indicators for optimzatin: \n', god_genes)
god_genes_with_timeperiod = list()
for god_gene in god_genes:
for timeperiod in timeperiods:
# print(f'{god_gene}-{timeperiod}')
god_genes_with_timeperiod.append(f'{god_gene}-{timeperiod}')
# Let give somethings to CatagoricalParam to Play with them
# When just one thing is inside catagorical lists
# TODO: its Not True Way :)
if len(god_genes) == 1:
god_genes = god_genes*2
if len(timeperiods) == 1:
timeperiods = timeperiods*2
if len(operators) == 1:
operators = operators*2
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):
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] > dataframe[crossed_indicator]
)
elif operator == "=":
condition = (
np.isclose(dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "<":
condition = (
dataframe[indicator] < dataframe[crossed_indicator]
)
elif operator == "C":
condition = (
(qtpylib.crossed_below(dataframe[indicator], dataframe[crossed_indicator])) |
(qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator]))
)
elif operator == "CA":
condition = (
qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "CB":
condition = (
qtpylib.crossed_below(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == ">R":
condition = (
dataframe[indicator] > real_num
)
elif operator == "=R":
condition = (
np.isclose(dataframe[indicator], real_num)
)
elif operator == "<R":
condition = (
dataframe[indicator] < real_num
)
elif operator == "/>R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) > real_num
)
elif operator == "/=R":
condition = (
np.isclose(dataframe[indicator].div(
dataframe[crossed_indicator]), real_num)
)
elif operator == "/<R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) < real_num
)
elif operator == "UT":
condition = (
dataframe[indicator] > dataframe[indicator_trend_sma]
)
elif operator == "DT":
condition = (
dataframe[indicator] < dataframe[indicator_trend_sma]
)
elif operator == "OT":
condition = (
np.isclose(dataframe[indicator], dataframe[indicator_trend_sma])
)
elif operator == "CUT":
condition = (
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] > dataframe[indicator_trend_sma]
)
)
elif operator == "CDT":
condition = (
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] < dataframe[indicator_trend_sma]
)
)
elif operator == "COT":
condition = (
(
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) |
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
) &
(
np.isclose(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
)
return condition, dataframe
class GodStraJD3_6(IStrategy):
# #################### RESULTS PASTE PLACE ####################
# ROI table:
minimal_roi = {
"0": 1,
# "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'},
'sma10': {'color': 'yellow'},
'min': {'color': 'white'},
'max': {'color': 'white'},
'sma20': {'color': 'cyan'}
},
'subplots': {
# Subplots - each dict defines one additional plot
"BB": {
'bb_width': {'color': 'white'},
'bb_min': {'color': 'red'},
},
"Ind": {
'MA-20': {'color': 'green'},
'STOCH-1-10': {'color': 'blue'},
'CDLDRAGONFLYDOJI-5': {'color': 'red'}
},
"Ind2": {
'MINUS_DM-5': {'color': 'green'},
'DX-5': {'color': 'blue'},
'LINEARREG-50': {'color': 'red'}
},
"Profit": {
'profit': {'color': 'pink'},
},
"Rsi": {
'rsi': {'color': 'pink'},
},
# "rolling": {
# 'bb_rolling': {'color': '#87e470'},
# "bb_rolling_min": {'color': '#ac3e2a'}
# },
"percent": {
"percent": {'color': 'green'},
"percent3": {'color': 'blue'},
"percent5": {'color': 'red'}
}
}
}
# #################### END OF RESULT PLACE ####################
# TODO: Its not dry code!
# Buy Hyperoptable Parameters/Spaces.
buy_crossed_indicator0 = CategoricalParameter(god_genes_with_timeperiod, default="ADD-20", space='buy')
buy_crossed_indicator1 = CategoricalParameter(god_genes_with_timeperiod, default="ASIN-6", space='buy')
buy_crossed_indicator2 = CategoricalParameter(god_genes_with_timeperiod, default="CDLEVENINGSTAR-50", space='buy')
buy_indicator0 = CategoricalParameter(god_genes_with_timeperiod, default="SMA-100", space='buy')
buy_indicator1 = CategoricalParameter(god_genes_with_timeperiod, default="WILLR-50", space='buy')
buy_indicator2 = CategoricalParameter(god_genes_with_timeperiod, default="CDLHANGINGMAN-20", space='buy')
buy_operator0 = CategoricalParameter(operators, default="/<R", space='buy')
buy_operator1 = CategoricalParameter(operators, default="<R", space='buy')
buy_operator2 = CategoricalParameter(operators, default="CB", space='buy')
buy_real_num0 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.89009, space='buy')
buy_real_num1 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.56953, space='buy')
buy_real_num2 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.38365, space='buy')
# Sell Hyperoptable Parameters/Spaces.
sell_crossed_indicator0 = CategoricalParameter(god_genes_with_timeperiod, default="CDLSHOOTINGSTAR-150", space='sell')
sell_crossed_indicator1 = CategoricalParameter(god_genes_with_timeperiod, default="MAMA-1-100", space='sell')
sell_crossed_indicator2 = CategoricalParameter(god_genes_with_timeperiod, default="CDLMATHOLD-6", space='sell')
sell_indicator0 = CategoricalParameter(god_genes_with_timeperiod, default="CDLUPSIDEGAP2CROWS-5", space='sell')
sell_indicator1 = CategoricalParameter(god_genes_with_timeperiod, default="CDLHARAMICROSS-150", space='sell')
sell_indicator2 = CategoricalParameter(god_genes_with_timeperiod, default="CDL2CROWS-5", space='sell')
sell_operator0 = CategoricalParameter(operators, default="<R", space='sell')
sell_operator1 = CategoricalParameter(operators, default="D", space='sell')
sell_operator2 = CategoricalParameter(operators, default="/>R", space='sell')
sell_real_num0 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.09731, space='sell')
sell_real_num1 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.81657, space='sell')
sell_real_num2 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.87267, space='sell')
@property
def protections(self):
return [
{
"method": "CooldownPeriod",
"stop_duration_candles": 10
},
{
"method": "MaxDrawdown",
"lookback_period_candles": 48,
"trade_limit": 2,
"stop_duration_candles": 10,
"max_allowed_drawdown": 0.04,
"only_per_pair": False
},
# {
# "method": "StoplossGuard",
# "lookback_period_candles": 24,
# "trade_limit": 4,
# "stop_duration_candles": 2,
# "only_per_pair": False
# },
# {
# "method": "LowProfitPairs",
# "lookback_period_candles": 6,
# "trade_limit": 2,
# "stop_duration_candles": 60,
# "required_profit": 0.02
# },
# {
# "method": "LowProfitPairs",
# "lookback_period_candles": 24,
# "trade_limit": 4,
# "stop_duration_candles": 2,
# "required_profit": 0.01
# }
]
# def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
# proposed_stake: float, min_stake: float, max_stake: float,
# **kwargs) -> float:
#
# dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
# current_candle = dataframe.iloc[-1].squeeze()
#
# # print("proposed_stake=", proposed_stake, " max_stake=", max_stake)
# if current_candle['bb_width'] > 0.065:
# # print("use more stake", pair, " ", proposed_stake * 2)
# return min(max_stake, proposed_stake * 2)
#
# if current_candle['bb_width'] > 0.045:
# # print("use more stake", pair, " ", proposed_stake * 1.5)
# return min(max_stake, proposed_stake * 1.5)
#
# # if current_candle['bb_width'] < 0.020:
# # print("use less stake", pair, " ", proposed_stake / 2)
# # return min(max_stake, proposed_stake / 2)
# # if self.config['stake_amount'] == 'unlimited':
# # # Use entire available wallet during favorable conditions when in compounding mode.
# # return max_stake
# # else:
# # # Compound profits during favorable conditions instead of using a static stake.
# # return self.wallets.get_total_stake_amount() / self.config['max_open_trades']
#
# # Use default stake amount.
# return proposed_stake
# 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()
# #print("last_candle", last_candle)
# #print("previous_last_candle", previous_last_candle)
#
# #dataframe.iloc[-1]['profit'] = current_profit
# count = 0
# for coin, balance in self.wallets.get_all_balances().items():
# count = count + 1
# # print(coin, " ", balance)
# # print("count=", count)
#
# # (last_candle['percent5'] < -0.005) \
# # if (0 < current_profit < 0.005) \
# # & ((current_time - trade.open_date_utc).seconds >= 3600 * 2):
# # # & (previous_last_candle['sma10'] > last_candle['sma10']):
# # print("too_small_gain", pair, trade, " profit=", current_profit, " rate=", current_rate, " percent5=",
# # last_candle['percent5'])
# # return 'too_small_gain'
#
# # if (current_profit < -0.05) \
# # & ((current_time - trade.open_date_utc).days >= 3):
# # print("lost_half_profit", pair, trade, " profit=", current_profit, " rate=", current_rate)
# # return 'stop_loss_profit'
#
# # if (current_profit > 0.02) \
# # & (last_candle['percent'] < 0.01) \
# # & ((current_time - trade.open_date_utc).seconds >= 3600):
# # print("lost_half_profit", pair, trade, " profit=", current_profit, " rate=", current_rate)
# # return 'lost_half_profit'
#
# # ((current_time - trade.open_date_utc).seconds >= 3600 * 2) \
# if (current_profit > 0) \
# & ((previous_5_candle['sma10'] > last_candle['sma10'] * 1.005) | (last_candle['percent3'] < -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 'over_bb_band_sma10_desc'
#
# # if (current_profit > 0) \
# # & (last_candle['percent'] < -0.02):
# # # print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
# # return 'stop_percent_loss'
#
# #if (current_profit > 0) \
# # & ((current_time - trade.open_date_utc).seconds >= 3600 * 2) \
# # & (previous_last_candle['sma20'] > last_candle['sma20']) \
# # & (last_candle['percent'] < 0):
# # print("over_bb_band_sma20_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
# # return 'over_bb_band_sma20_desc'
#
# if (current_profit > 0) \
# & (last_candle['rsi'] > 88): #| (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)):
# # print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
# return 'over_rsi'
#
# # description trade
# # Trade(id=0, pair=CAKE/USDT, amount=4.19815281, open_rate=11.91000000, open_since=2021-12-22 17:55:00)
# # print(last_candle)
# #if 0.015 < current_profit < 0.03:
# # if (last_candle['percent3'] < -0.005 ):
# # # self.lock_pair(pair, until=current_time + timedelta(hours=3))
# # print("profit_3h_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
# # return 'profit_percent3'
#
# #
# # if (0 < current_profit < 0.1) \
# # & (previous_last_candle['sma20'] > last_candle['sma20']) \
# # & ((current_time - trade.open_date_utc).seconds >= 3600 * 5):
# # print("profit_5h_sma20_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
# # return 'profit_5h_sma20_desc'
#
# # if (count == self.config['max_open_trades']) & (current_profit < -0.04) \
# # & ((current_time - trade.open_date_utc).seconds >= 3600 * 6):
# # self.lock_pair(pair, until=current_time + timedelta(hours=10))
# # print("stop_short_loss", pair, trade, " profit=", current_profit, " rate=", current_rate,
# # "count=", count, "max=", self.config['max_open_trades'])
# # return 'stop_short_loss'
def informative_pairs(self):
return []
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# MACD
# macd = ta.MACD(dataframe)
# dataframe['macd'] = macd['macd']
# dataframe['macdsignal'] = macd['macdsignal']
# dataframe['macdhist'] = macd['macdhist']
# # # Plus Directional Indicator / Movement
# dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
# dataframe['plus_di'] = ta.PLUS_DI(dataframe)
#
# # Minus Directional Indicator / Movement
# dataframe['adx'] = ta.ADX(dataframe)
dataframe['MINUS_DM-5'] = gene_calculator(dataframe, 'MINUS_DM-5')
dataframe['LINEARREG-50'] = gene_calculator(dataframe, 'LINEARREG-50')
dataframe['MA-20'] = gene_calculator(dataframe, 'MA-20')
dataframe['STOCH-1-10'] = gene_calculator(dataframe, 'STOCH-1-10')
dataframe['CDLDRAGONFLYDOJI-5'] = gene_calculator(dataframe, 'CDLDRAGONFLYDOJI-5')
dataframe['DX-5'] = gene_calculator(dataframe, 'DX-5')
# dataframe['MINUS_DM-5'] = ta.MINUS_DM(dataframe, timeperiod=5)
# dataframe['LINEARREG-50'] = ta.LINEARREG(dataframe, timeperiod=50)
# dataframe['MA-20'] = ta.MA(dataframe, timeperiod=20)
# stoch = ta.STOCH(dataframe, timeperiod=10)
# # print(stoch)
# dataframe['STOCH-1-10'] = stoch['slowd']
# dataframe['CDLDRAGONFLYDOJI-5'] = ta.CDLDRAGONFLYDOJI(dataframe, timeperiod=5)
# dataframe['minus_di'] = ta.MINUS_DI(dataframe)
# dataframe['min'] = ta.MIN(dataframe)
# dataframe['max'] = ta.MAX(dataframe)
# # Aroon, Aroon Oscillator
# aroon = ta.AROON(dataframe)
# dataframe['aroonup'] = aroon['aroonup']
# dataframe['aroondown'] = aroon['aroondown']
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
dataframe['profit'] = 0
# RSI
dataframe['rsi'] = ta.RSI(dataframe)
# # EMA - Exponential Moving Average
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
# dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
# # SMA - Simple Moving Average
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
# 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['sma200'] = ta.SMA(dataframe, timeperiod=200)
# dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
# dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
# dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
dataframe["percent"] = (dataframe["close"] - dataframe["open"]) / dataframe["open"]
dataframe["percent5"] = dataframe["percent"].rolling(5).sum()
dataframe["percent3"] = dataframe["percent"].rolling(3).sum()
dataframe["percent20"] = dataframe["percent"].rolling(20).sum()
dataframe['min'] = ta.MIN(dataframe['close'], timeperiod=200)
dataframe['min20'] = ta.MIN(dataframe['close'], timeperiod=20)
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_min'] = ta.MIN(dataframe['bb_lowerband'], timeperiod=36)
# 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"]
# )
# # EMA - Exponential Moving Average
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = list()
# TODO: Its not dry code!
buy_indicator = self.buy_indicator0.value
buy_crossed_indicator = self.buy_crossed_indicator0.value
buy_operator = self.buy_operator0.value
buy_real_num = self.buy_real_num0.value
condition, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition)
# backup
buy_indicator = self.buy_indicator1.value
buy_crossed_indicator = self.buy_crossed_indicator1.value
buy_operator = self.buy_operator1.value
buy_real_num = self.buy_real_num1.value
condition, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition)
buy_indicator = self.buy_indicator2.value
buy_crossed_indicator = self.buy_crossed_indicator2.value
buy_operator = self.buy_operator2.value
buy_real_num = self.buy_real_num2.value
condition, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition)
if conditions:
dataframe.loc[
# (
# (dataframe['close'] < dataframe['bb_lowerband'])
# & (dataframe['bb_width'] >= 0.045)
# & (dataframe['volume'] * dataframe['close'] / 1000 > 100)
# ) |
(reduce(lambda x, y: x & y, conditions)),
'buy']=1
# print(len(dataframe.keys()))
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = list()
# TODO: Its not dry code!
sell_indicator = self.sell_indicator0.value
sell_crossed_indicator = self.sell_crossed_indicator0.value
sell_operator = self.sell_operator0.value
sell_real_num = self.sell_real_num0.value
condition, dataframe = condition_generator(
dataframe,
sell_operator,
sell_indicator,
sell_crossed_indicator,
sell_real_num
)
conditions.append(condition)
sell_indicator = self.sell_indicator1.value
sell_crossed_indicator = self.sell_crossed_indicator1.value
sell_operator = self.sell_operator1.value
sell_real_num = self.sell_real_num1.value
condition, dataframe = condition_generator(
dataframe,
sell_operator,
sell_indicator,
sell_crossed_indicator,
sell_real_num
)
conditions.append(condition)
sell_indicator = self.sell_indicator2.value
sell_crossed_indicator = self.sell_crossed_indicator2.value
sell_operator = self.sell_operator2.value
sell_real_num = self.sell_real_num2.value
condition, dataframe = condition_generator(
dataframe,
sell_operator,
sell_indicator,
sell_crossed_indicator,
sell_real_num
)
conditions.append(condition)
#dataframe.loc[(dataframe['close'] < dataframe['bb_lowerband']),'sell']=1
# count = 0
# for coin, balance in self.wallets.get_all_balances().items():
# count = count + 1
# # print(coin, " ", balance)
# if (count == self.config['max_open_trades']) & (current_profit < -0.04) \
# & ((current_time - trade.open_date_utc).seconds >= 3600 * 6):
# self.lock_pair(pair, until=current_time + timedelta(hours=10))
# print("stop_short_loss", pair, trade, " profit=", current_profit, " rate=", current_rate,
# "count=", count, "max=", self.config['max_open_trades'])
# return 'stop_short_loss'
# print("sell pair=", self.wallets.get_all_balances()[metadata['pair']])
if conditions:
dataframe.loc[
(
reduce(lambda x, y: x & y, conditions) &
(dataframe['volume'] * dataframe['close'] / 1000 >= 100)
# (dataframe['open'] < dataframe['sma10'])
),
'sell']=1
return dataframe

48
GodStraJD3_6_53.json Normal file
View File

@@ -0,0 +1,48 @@
{
"strategy_name": "GodStraJD3_6_53",
"params": {
"roi": {
"0": 1
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.15,
"trailing_stop_positive_offset": 0.2,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_crossed_indicator0": "HT_TRENDLINE-100",
"buy_crossed_indicator1": "MACD-1-100",
"buy_crossed_indicator2": "CCI-20",
"buy_indicator0": "CDLDOJISTAR-10",
"buy_indicator1": "WCLPRICE-10",
"buy_indicator2": "DEMA-50",
"buy_operator0": "/>R",
"buy_operator1": "<R",
"buy_operator2": "<",
"buy_real_num0": 0.92,
"buy_real_num1": 0.4,
"buy_real_num2": 0.04
},
"sell": {
"sell_crossed_indicator0": "MIDPOINT-10",
"sell_crossed_indicator1": "CDLTRISTAR-10",
"sell_crossed_indicator2": "CDLBELTHOLD-50",
"sell_indicator0": "CDLLONGLINE-20",
"sell_indicator1": "STOCHF-1-50",
"sell_indicator2": "MACDEXT-0-5",
"sell_operator0": "<",
"sell_operator1": ">R",
"sell_operator2": ">",
"sell_real_num0": 0.1,
"sell_real_num1": 0.8,
"sell_real_num2": 1.0
},
"protection": {}
},
"ft_stratparam_v": 1,
"export_time": "2022-02-01 22:59:30.762086+00:00"
}

48
GodStraJD3_6_53.jsonOLD Normal file
View File

@@ -0,0 +1,48 @@
{
"strategy_name": "GodStraJD3_6_53",
"params": {
"roi": {
"0": 1
},
"stoploss": {
"stoploss": -2.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.15,
"trailing_stop_positive_offset": 0.2,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_crossed_indicator0": "HT_TRENDLINE-100",
"buy_crossed_indicator1": "MACD-1-100",
"buy_crossed_indicator2": "CCI-20",
"buy_indicator0": "CDLDOJISTAR-10",
"buy_indicator1": "WCLPRICE-10",
"buy_indicator2": "DEMA-50",
"buy_operator0": "/>R",
"buy_operator1": "<R",
"buy_operator2": "<",
"buy_real_num0": 0.92,
"buy_real_num1": 0.4,
"buy_real_num2": 0.04
},
"sell": {
"sell_crossed_indicator0": "CDLSHOOTINGSTAR-150",
"sell_crossed_indicator1": "MAMA-1-100",
"sell_crossed_indicator2": "CDLMATHOLD-6",
"sell_indicator0": "CDLUPSIDEGAP2CROWS-5",
"sell_indicator1": "CDLHARAMICROSS-150",
"sell_indicator2": "CDL2CROWS-5",
"sell_operator0": "<R",
"sell_operator1": "D",
"sell_operator2": "/>R",
"sell_real_num0": 0.1,
"sell_real_num1": 0.8,
"sell_real_num2": 0.9
},
"protection": {}
},
"ft_stratparam_v": 1,
"export_time": "2022-01-15 13:26:31.727849+00:00"
}

973
GodStraJD3_6_53.py Normal file
View File

@@ -0,0 +1,973 @@
# 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 freqtrade import data
from freqtrade.persistence import Trade
from freqtrade.strategy.parameters import CategoricalParameter, DecimalParameter, IntParameter
from numpy.lib import math
from freqtrade.strategy.interface import IStrategy, SellCheckTuple
from pandas import DataFrame
# --------------------------------
# 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
# TODO: this gene is removed 'MAVP' cuz or error on periods
all_god_genes = {
'Overlap Studies': {
'BBANDS-0', # Bollinger Bands
'BBANDS-1', # Bollinger Bands
'BBANDS-2', # Bollinger Bands
'DEMA', # Double Exponential Moving Average
'EMA', # Exponential Moving Average
'HT_TRENDLINE', # Hilbert Transform - Instantaneous Trendline
'KAMA', # Kaufman Adaptive Moving Average
'MA', # Moving average
'MAMA-0', # MESA Adaptive Moving Average
'MAMA-1', # MESA Adaptive Moving Average
# TODO: Fix this
# 'MAVP', # Moving average with variable period
'MIDPOINT', # MidPoint over period
'MIDPRICE', # Midpoint Price over period
'SAR', # Parabolic SAR
'SAREXT', # Parabolic SAR - Extended
'SMA', # Simple Moving Average
'T3', # Triple Exponential Moving Average (T3)
'TEMA', # Triple Exponential Moving Average
'TRIMA', # Triangular Moving Average
'WMA', # Weighted Moving Average
},
'Momentum Indicators': {
'ADX', # Average Directional Movement Index
'ADXR', # Average Directional Movement Index Rating
'APO', # Absolute Price Oscillator
'AROON-0', # Aroon
'AROON-1', # Aroon
'AROONOSC', # Aroon Oscillator
'BOP', # Balance Of Power
'CCI', # Commodity Channel Index
'CMO', # Chande Momentum Oscillator
'DX', # Directional Movement Index
'MACD-0', # Moving Average Convergence/Divergence
'MACD-1', # Moving Average Convergence/Divergence
'MACD-2', # Moving Average Convergence/Divergence
'MACDEXT-0', # MACD with controllable MA type
'MACDEXT-1', # MACD with controllable MA type
'MACDEXT-2', # MACD with controllable MA type
'MACDFIX-0', # Moving Average Convergence/Divergence Fix 12/26
'MACDFIX-1', # Moving Average Convergence/Divergence Fix 12/26
'MACDFIX-2', # Moving Average Convergence/Divergence Fix 12/26
'MFI', # Money Flow Index
'MINUS_DI', # Minus Directional Indicator
'MINUS_DM', # Minus Directional Movement
'MOM', # Momentum
'PLUS_DI', # Plus Directional Indicator
'PLUS_DM', # Plus Directional Movement
'PPO', # Percentage Price Oscillator
'ROC', # Rate of change : ((price/prevPrice)-1)*100
# Rate of change Percentage: (price-prevPrice)/prevPrice
'ROCP',
'ROCR', # Rate of change ratio: (price/prevPrice)
# Rate of change ratio 100 scale: (price/prevPrice)*100
'ROCR100',
'RSI', # Relative Strength Index
'STOCH-0', # Stochastic
'STOCH-1', # Stochastic
'STOCHF-0', # Stochastic Fast
'STOCHF-1', # Stochastic Fast
'STOCHRSI-0', # Stochastic Relative Strength Index
'STOCHRSI-1', # Stochastic Relative Strength Index
# 1-day Rate-Of-Change (ROC) of a Triple Smooth EMA
'TRIX',
'ULTOSC', # Ultimate Oscillator
'WILLR', # Williams' %R
},
'Volume Indicators': {
'AD', # Chaikin A/D Line
'ADOSC', # Chaikin A/D Oscillator
'OBV', # On Balance Volume
},
'Volatility Indicators': {
'ATR', # Average True Range
'NATR', # Normalized Average True Range
'TRANGE', # True Range
},
'Price Transform': {
'AVGPRICE', # Average Price
'MEDPRICE', # Median Price
'TYPPRICE', # Typical Price
'WCLPRICE', # Weighted Close Price
},
'Cycle Indicators': {
'HT_DCPERIOD', # Hilbert Transform - Dominant Cycle Period
'HT_DCPHASE', # Hilbert Transform - Dominant Cycle Phase
'HT_PHASOR-0', # Hilbert Transform - Phasor Components
'HT_PHASOR-1', # Hilbert Transform - Phasor Components
'HT_SINE-0', # Hilbert Transform - SineWave
'HT_SINE-1', # Hilbert Transform - SineWave
'HT_TRENDMODE', # Hilbert Transform - Trend vs Cycle Mode
},
'Pattern Recognition': {
'CDL2CROWS', # Two Crows
'CDL3BLACKCROWS', # Three Black Crows
'CDL3INSIDE', # Three Inside Up/Down
'CDL3LINESTRIKE', # Three-Line Strike
'CDL3OUTSIDE', # Three Outside Up/Down
'CDL3STARSINSOUTH', # Three Stars In The South
'CDL3WHITESOLDIERS', # Three Advancing White Soldiers
'CDLABANDONEDBABY', # Abandoned Baby
'CDLADVANCEBLOCK', # Advance Block
'CDLBELTHOLD', # Belt-hold
'CDLBREAKAWAY', # Breakaway
'CDLCLOSINGMARUBOZU', # Closing Marubozu
'CDLCONCEALBABYSWALL', # Concealing Baby Swallow
'CDLCOUNTERATTACK', # Counterattack
'CDLDARKCLOUDCOVER', # Dark Cloud Cover
'CDLDOJI', # Doji
'CDLDOJISTAR', # Doji Star
'CDLDRAGONFLYDOJI', # Dragonfly Doji
'CDLENGULFING', # Engulfing Pattern
'CDLEVENINGDOJISTAR', # Evening Doji Star
'CDLEVENINGSTAR', # Evening Star
'CDLGAPSIDESIDEWHITE', # Up/Down-gap side-by-side white lines
'CDLGRAVESTONEDOJI', # Gravestone Doji
'CDLHAMMER', # Hammer
'CDLHANGINGMAN', # Hanging Man
'CDLHARAMI', # Harami Pattern
'CDLHARAMICROSS', # Harami Cross Pattern
'CDLHIGHWAVE', # High-Wave Candle
'CDLHIKKAKE', # Hikkake Pattern
'CDLHIKKAKEMOD', # Modified Hikkake Pattern
'CDLHOMINGPIGEON', # Homing Pigeon
'CDLIDENTICAL3CROWS', # Identical Three Crows
'CDLINNECK', # In-Neck Pattern
'CDLINVERTEDHAMMER', # Inverted Hammer
'CDLKICKING', # Kicking
'CDLKICKINGBYLENGTH', # Kicking - bull/bear determined by the longer marubozu
'CDLLADDERBOTTOM', # Ladder Bottom
'CDLLONGLEGGEDDOJI', # Long Legged Doji
'CDLLONGLINE', # Long Line Candle
'CDLMARUBOZU', # Marubozu
'CDLMATCHINGLOW', # Matching Low
'CDLMATHOLD', # Mat Hold
'CDLMORNINGDOJISTAR', # Morning Doji Star
'CDLMORNINGSTAR', # Morning Star
'CDLONNECK', # On-Neck Pattern
'CDLPIERCING', # Piercing Pattern
'CDLRICKSHAWMAN', # Rickshaw Man
'CDLRISEFALL3METHODS', # Rising/Falling Three Methods
'CDLSEPARATINGLINES', # Separating Lines
'CDLSHOOTINGSTAR', # Shooting Star
'CDLSHORTLINE', # Short Line Candle
'CDLSPINNINGTOP', # Spinning Top
'CDLSTALLEDPATTERN', # Stalled Pattern
'CDLSTICKSANDWICH', # Stick Sandwich
# Takuri (Dragonfly Doji with very long lower shadow)
'CDLTAKURI',
'CDLTASUKIGAP', # Tasuki Gap
'CDLTHRUSTING', # Thrusting Pattern
'CDLTRISTAR', # Tristar Pattern
'CDLUNIQUE3RIVER', # Unique 3 River
'CDLUPSIDEGAP2CROWS', # Upside Gap Two Crows
'CDLXSIDEGAP3METHODS', # Upside/Downside Gap Three Methods
},
'Statistic Functions': {
'BETA', # Beta
'CORREL', # Pearson's Correlation Coefficient (r)
'LINEARREG', # Linear Regression
'LINEARREG_ANGLE', # Linear Regression Angle
'LINEARREG_INTERCEPT', # Linear Regression Intercept
'LINEARREG_SLOPE', # Linear Regression Slope
'STDDEV', # Standard Deviation
'TSF', # Time Series Forecast
'VAR', # Variance
}
}
god_genes = set()
########################### SETTINGS ##############################
# god_genes = {'SMA'}
god_genes |= all_god_genes['Overlap Studies']
god_genes |= all_god_genes['Momentum Indicators']
god_genes |= all_god_genes['Volume Indicators']
god_genes |= all_god_genes['Volatility Indicators']
god_genes |= all_god_genes['Price Transform']
god_genes |= all_god_genes['Cycle Indicators']
god_genes |= all_god_genes['Pattern Recognition']
god_genes |= all_god_genes['Statistic Functions']
#timeperiods = [5, 6, 12, 15, 50, 55, 100, 110]
timeperiods = [5, 10, 20, 50, 100]
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
ind_1 = 'HT_TRENDLINE-100'
ind_2 = 'MACD-1-100'
ind_3 = 'CCI-20'
ind_4 = 'CDLDOJISTAR-10'
ind_5 = 'WCLPRICE-10'
ind_6 = 'DEMA-50'
sell_1 = "CDLLONGLINE-20"
sell_2 = "STOCHF-1-50"
sell_3 = "MACDEXT-0-5"
sell_4 = "MIDPOINT-10"
sell_5 = "CDLTRISTAR-10"
sell_6 = "CDLBELTHOLD-50"
########################### END SETTINGS ##########################
# DATAFRAME = DataFrame()
god_genes = list(god_genes)
# print('selected indicators for optimzatin: \n', god_genes)
god_genes_with_timeperiod = list()
for god_gene in god_genes:
for timeperiod in timeperiods:
# print(f'{god_gene}-{timeperiod}')
god_genes_with_timeperiod.append(f'{god_gene}-{timeperiod}')
# Let give somethings to CatagoricalParam to Play with them
# When just one thing is inside catagorical lists
# TODO: its Not True Way :)
if len(god_genes) == 1:
god_genes = god_genes*2
if len(timeperiods) == 1:
timeperiods = timeperiods*2
if len(operators) == 1:
operators = operators*2
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):
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] > dataframe[crossed_indicator]
)
elif operator == "=":
condition = (
np.isclose(dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "<":
condition = (
dataframe[indicator] < dataframe[crossed_indicator]
)
elif operator == "C":
condition = (
(qtpylib.crossed_below(dataframe[indicator], dataframe[crossed_indicator])) |
(qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator]))
)
elif operator == "CA":
condition = (
qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "CB":
condition = (
qtpylib.crossed_below(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == ">R":
condition = (
dataframe[indicator] > real_num
)
elif operator == "=R":
condition = (
np.isclose(dataframe[indicator], real_num)
)
elif operator == "<R":
condition = (
dataframe[indicator] < real_num
)
elif operator == "/>R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) > real_num
)
elif operator == "/=R":
condition = (
np.isclose(dataframe[indicator].div(
dataframe[crossed_indicator]), real_num)
)
elif operator == "/<R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) < real_num
)
elif operator == "UT":
condition = (
dataframe[indicator] > dataframe[indicator_trend_sma]
)
elif operator == "DT":
condition = (
dataframe[indicator] < dataframe[indicator_trend_sma]
)
elif operator == "OT":
condition = (
np.isclose(dataframe[indicator], dataframe[indicator_trend_sma])
)
elif operator == "CUT":
condition = (
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] > dataframe[indicator_trend_sma]
)
)
elif operator == "CDT":
condition = (
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] < dataframe[indicator_trend_sma]
)
)
elif operator == "COT":
condition = (
(
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) |
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
) &
(
np.isclose(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
)
return condition, dataframe
class GodStraJD3_6_53(IStrategy):
# #################### RESULTS PASTE PLACE ####################
# ROI table:
minimal_roi = {
"0": 1,
# "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'},
'sma10': {'color': 'yellow'},
# 'min': {'color': 'white'},
# 'max': {'color': 'white'},
'sma20': {'color': 'cyan'}
},
'subplots': {
# Subplots - each dict defines one additional plot
# "BB": {
# 'bb_width': {'color': 'white'},
# 'bb_min': {'color': 'red'},
# },
# "Ind": {
# ind_1: {'color': 'green'},
# ind_2: {'color': 'blue'},
# ind_3: {'color': 'red'}
# },
# "Ind2": {
# ind_4: {'color': 'green'},
# ind_5: {'color': 'blue'},
# ind_6: {'color': 'red'}
# },
"Pentes": {
'pente5': {'color': 'green'},
'pente10': {'color': 'pink'},
'pente20': {'color': 'green'},
'pente50': {'color': 'yellow'}
},
# "Rsi": {
# 'rsi': {'color': 'pink'},
# },
# "rolling": {
# 'bb_rolling': {'color': '#87e470'},
# "bb_rolling_min": {'color': '#ac3e2a'}
# },
"percent": {
"percent3": {'color': 'blue'},
"percent5": {'color': 'red'},
"percent10": {'color': 'green'},
"percent20": {'color': 'red'},
"percent50": {'color': 'pink'}
}
}
}
# #################### END OF RESULT PLACE ####################
# TODO: Its not dry code!
# Buy Hyperoptable Parameters/Spaces.
buy_crossed_indicator0 = CategoricalParameter(god_genes_with_timeperiod, default="ADD-20", space='buy')
buy_crossed_indicator1 = CategoricalParameter(god_genes_with_timeperiod, default="ASIN-6", space='buy')
buy_crossed_indicator2 = CategoricalParameter(god_genes_with_timeperiod, default="CDLEVENINGSTAR-50", space='buy')
buy_indicator0 = CategoricalParameter(god_genes_with_timeperiod, default="SMA-100", space='buy')
buy_indicator1 = CategoricalParameter(god_genes_with_timeperiod, default="WILLR-50", space='buy')
buy_indicator2 = CategoricalParameter(god_genes_with_timeperiod, default="CDLHANGINGMAN-20", space='buy')
buy_operator0 = CategoricalParameter(operators, default="/<R", space='buy')
buy_operator1 = CategoricalParameter(operators, default="<R", space='buy')
buy_operator2 = CategoricalParameter(operators, default="CB", space='buy')
buy_real_num0 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.89009, space='buy')
buy_real_num1 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.56953, space='buy')
buy_real_num2 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.38365, space='buy')
# Sell Hyperoptable Parameters/Spaces.
sell_crossed_indicator0 = CategoricalParameter(god_genes_with_timeperiod, default="CDLSHOOTINGSTAR-150", space='sell')
sell_crossed_indicator1 = CategoricalParameter(god_genes_with_timeperiod, default="MAMA-1-100", space='sell')
sell_crossed_indicator2 = CategoricalParameter(god_genes_with_timeperiod, default="CDLMATHOLD-6", space='sell')
sell_indicator0 = CategoricalParameter(god_genes_with_timeperiod, default="CDLUPSIDEGAP2CROWS-5", space='sell')
sell_indicator1 = CategoricalParameter(god_genes_with_timeperiod, default="CDLHARAMICROSS-150", space='sell')
sell_indicator2 = CategoricalParameter(god_genes_with_timeperiod, default="CDL2CROWS-5", space='sell')
sell_operator0 = CategoricalParameter(operators, default="<R", space='sell')
sell_operator1 = CategoricalParameter(operators, default="D", space='sell')
sell_operator2 = CategoricalParameter(operators, default="/>R", space='sell')
sell_real_num0 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.09731, space='sell')
sell_real_num1 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.81657, space='sell')
sell_real_num2 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.87267, space='sell')
protection_max_allowed_dd = DecimalParameter(0, 1, decimals=DECIMALS, default=0.04, space='protection')
protection_stop = IntParameter(0, 100, default=48, space='protection')
protection_stoploss_stop = IntParameter(0, 100, default=48, space='protection')
lookback = IntParameter(0, 200, default=48, space='protection')
trade_limit = IntParameter(0, 10, default=2, space='protection')
@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
}
]
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 (current_profit >= 0) & \
(
(last_candle['percent3'] < -0.01) |
((last_candle['percent'] < -0.01) & (previous_last_candle['rsi'] > 72))
):
return "quick_lost"
if (current_profit > 0.005) & (last_candle['percent10'] < 0.001):
return "no_change"
#if (current_profit > 0.01) & (last_candle['rsi'] < 30):
# return "small_rsi"
if (current_profit >= 0.03) & (last_candle['percent3'] < 0) & ((current_time - trade.open_date_utc).seconds <= 3600):
return "quick_gain_3"
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.01) \
& ((previous_5_candle['sma10'] > last_candle['sma10'] * 1.005) \
| (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 (current_profit > 0.005) & (last_candle['percent5'] < 0) \
& ((current_time - trade.open_date_utc).seconds >= 3600) \
& ((previous_last_candle['sma20'] > last_candle['sma20']) &
((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 (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 (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 (current_profit > 0) \
& (last_candle['rsi'] > 88): #| (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.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):
return []
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# MACD
# macd = ta.MACD(dataframe)
# dataframe['macd'] = macd['macd']
# dataframe['macdsignal'] = macd['macdsignal']
# dataframe['macdhist'] = macd['macdhist']
# # # Plus Directional Indicator / Movement
# dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
# dataframe['plus_di'] = ta.PLUS_DI(dataframe)
#
# # Minus Directional Indicator / Movement
# dataframe['adx'] = ta.ADX(dataframe)
dataframe[ind_1] = gene_calculator(dataframe, ind_1)
dataframe[ind_2] = gene_calculator(dataframe, ind_2)
dataframe[ind_3] = gene_calculator(dataframe, ind_3)
dataframe[ind_4] = gene_calculator(dataframe, ind_4)
dataframe[ind_5] = gene_calculator(dataframe, ind_5)
dataframe[ind_6] = gene_calculator(dataframe, ind_6)
dataframe[sell_1] = gene_calculator(dataframe, sell_1)
dataframe[sell_2] = gene_calculator(dataframe, sell_2)
dataframe[sell_3] = gene_calculator(dataframe, sell_3)
dataframe[sell_4] = gene_calculator(dataframe, sell_4)
dataframe[sell_5] = gene_calculator(dataframe, sell_5)
dataframe[sell_6] = gene_calculator(dataframe, sell_6)
# dataframe['MINUS_DM-5'] = ta.MINUS_DM(dataframe, timeperiod=5)
# dataframe['LINEARREG-50'] = ta.LINEARREG(dataframe, timeperiod=50)
# dataframe['MA-20'] = ta.MA(dataframe, timeperiod=20)
# stoch = ta.STOCH(dataframe, timeperiod=10)
# # print(stoch)
# dataframe['STOCH-1-10'] = stoch['slowd']
# dataframe['CDLDRAGONFLYDOJI-5'] = ta.CDLDRAGONFLYDOJI(dataframe, timeperiod=5)
# dataframe['minus_di'] = ta.MINUS_DI(dataframe)
# dataframe['min'] = ta.MIN(dataframe)
# dataframe['max'] = ta.MAX(dataframe)
# # Aroon, Aroon Oscillator
# aroon = ta.AROON(dataframe)
# dataframe['aroonup'] = aroon['aroonup']
# dataframe['aroondown'] = aroon['aroondown']
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
dataframe['profit'] = 0
# RSI
dataframe['rsi'] = ta.RSI(dataframe)
# # EMA - Exponential Moving Average
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
# dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
# # SMA - Simple Moving Average
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
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['sma200'] = ta.SMA(dataframe, timeperiod=200)
# dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
# dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
# dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
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['min'] = ta.MIN(dataframe['close'], timeperiod=200)
dataframe['min20'] = ta.MIN(dataframe['close'], timeperiod=20)
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_min'] = ta.MIN(dataframe['bb_lowerband'], timeperiod=36)
dataframe['pente5'] = (100 * (dataframe["sma5"] - dataframe["sma5"].shift(1)) / dataframe["sma5"])
dataframe['pente10'] = (100 * (dataframe["sma10"] - dataframe["sma10"].shift(1)) / dataframe["sma10"])
dataframe['pente20'] = (100 * (dataframe["sma20"] - dataframe["sma20"].shift(1)) / dataframe["sma20"])
dataframe['pente50'] = (100 * (dataframe["sma50"] - dataframe["sma50"].shift(1)) / dataframe["sma50"])
# 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"]
# )
# # EMA - Exponential Moving Average
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = list()
# TODO: Its not dry code!
buy_indicator = self.buy_indicator0.value
buy_crossed_indicator = self.buy_crossed_indicator0.value
buy_operator = self.buy_operator0.value
buy_real_num = self.buy_real_num0.value
condition1, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition1)
# backup
buy_indicator = self.buy_indicator1.value
buy_crossed_indicator = self.buy_crossed_indicator1.value
buy_operator = self.buy_operator1.value
buy_real_num = self.buy_real_num1.value
condition2, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition2)
buy_indicator = self.buy_indicator2.value
buy_crossed_indicator = self.buy_crossed_indicator2.value
buy_operator = self.buy_operator2.value
buy_real_num = self.buy_real_num2.value
condition3, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition3)
if conditions:
dataframe.loc[
(
(reduce(lambda x, y: x & y, conditions))
& (dataframe['volume10'] * dataframe['close'] / 1000 >= 10)
& (dataframe['close'] < dataframe['sma10'])
& (dataframe['open'] < dataframe['sma10'])
& (dataframe['low'] < dataframe['min20'])
) | (
(dataframe['volume10'] * dataframe['close'] / 1000 >= 10)
& (dataframe['percent20'].shift(10) < -0.03)
& (dataframe['pente10'].shift(5) < 0)
& (dataframe['pente10'] > 0)
& (dataframe['open'] < dataframe['sma10'])
& (dataframe['close'] < dataframe['sma10'])
& (dataframe['low'] < dataframe['min20'])
# ) | (
# (dataframe['volume10'] * dataframe['close'] / 1000 >= 10)
# & (dataframe['percent20'].shift(5) < -0.01)
# & (dataframe['percent3'] > 0)
# & (dataframe['open'] < dataframe['sma10'])
# & (dataframe['close'] < dataframe['sma10'])
# & (dataframe['sma100'].shift(1) < dataframe['sma100'])
# # & (dataframe['pente5'] > 0)
#
# ) | (
# (dataframe['volume10'].shift(1) * dataframe['close'].shift(1) / 1000 >= 10)
# & (dataframe['percent20'].shift(6) < -0.01)
# & (dataframe['percent3'].shift(1) > 0)
# & (dataframe['open'].shift(1) < dataframe['sma10'].shift(1))
# & (dataframe['close'].shift(1) < dataframe['sma10'].shift(1))
# & (dataframe['sma100'].shift(1) < dataframe['sma100'])
# # & (dataframe['pente5'].shift(1) > 0)
),
'buy']=1
# print(len(dataframe.keys()))
# print(
# reduce(lambda x, y: x & y, condition1), " ",
# reduce(lambda x, y: x & y, condition2), " ",
# reduce(lambda x, y: x & y, condition3), " ",
# # (reduce(lambda x, y: x & y, conditions))
# dataframe['buy'],
# )
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = list()
# TODO: Its not dry code!
sell_indicator = self.sell_indicator0.value
sell_crossed_indicator = self.sell_crossed_indicator0.value
sell_operator = self.sell_operator0.value
sell_real_num = self.sell_real_num0.value
condition, dataframe = condition_generator(
dataframe,
sell_operator,
sell_indicator,
sell_crossed_indicator,
sell_real_num
)
conditions.append(condition)
sell_indicator = self.sell_indicator1.value
sell_crossed_indicator = self.sell_crossed_indicator1.value
sell_operator = self.sell_operator1.value
sell_real_num = self.sell_real_num1.value
condition, dataframe = condition_generator(
dataframe,
sell_operator,
sell_indicator,
sell_crossed_indicator,
sell_real_num
)
conditions.append(condition)
sell_indicator = self.sell_indicator2.value
sell_crossed_indicator = self.sell_crossed_indicator2.value
sell_operator = self.sell_operator2.value
sell_real_num = self.sell_real_num2.value
condition, dataframe = condition_generator(
dataframe,
sell_operator,
sell_indicator,
sell_crossed_indicator,
sell_real_num
)
conditions.append(condition)
#dataframe.loc[(dataframe['close'] < dataframe['bb_lowerband']),'sell']=1
# count = 0
# for coin, balance in self.wallets.get_all_balances().items():
# count = count + 1
# # print(coin, " ", balance)
# if (count == self.config['max_open_trades']) & (current_profit < -0.04) \
# & ((current_time - trade.open_date_utc).seconds >= 3600 * 6):
# self.lock_pair(pair, until=current_time + timedelta(hours=10))
# print("stop_short_loss", pair, trade, " profit=", current_profit, " rate=", current_rate,
# "count=", count, "max=", self.config['max_open_trades'])
# return 'stop_short_loss'
# print("sell pair=", self.wallets.get_all_balances()[metadata['pair']])
# if conditions:
# dataframe.loc[
# (
# reduce(lambda x, y: x & y, conditions) #(dataframe['percent3'] > 0)
# ),
# 'sell']=1
return dataframe

51
GodStraJD3_6_53_1.json Normal file
View File

@@ -0,0 +1,51 @@
{
"strategy_name": "GodStraJD3_6_53_1",
"params": {
"roi": {
"0": 10
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.15,
"trailing_stop_positive_offset": 0.2,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_crossed_indicator0": "HT_TRENDLINE-100",
"buy_crossed_indicator1": "MACD-1-100",
"buy_crossed_indicator2": "CCI-20",
"buy_indicator0": "CDLDOJISTAR-10",
"buy_indicator1": "WCLPRICE-10",
"buy_indicator2": "DEMA-50",
"buy_operator0": "/>R",
"buy_operator1": "<R",
"buy_operator2": "<",
"buy_real_num0": 0.92,
"buy_real_num1": 0.4,
"buy_real_num2": 0.04
},
"sell": {
"sell_crossed_indicator0": "MIDPOINT-10",
"sell_crossed_indicator1": "CDLTRISTAR-10",
"sell_crossed_indicator2": "CDLBELTHOLD-50",
"sell_indicator0": "CDLLONGLINE-20",
"sell_indicator1": "STOCHF-1-50",
"sell_indicator2": "MACDEXT-0-5",
"sell_operator0": "<",
"sell_operator1": ">R",
"sell_operator2": ">",
"sell_real_num0": 0.1,
"sell_real_num1": 0.8,
"sell_real_num2": 1.0
},
"protection": {
"protection_max_allowed_dd": 0.36,
"protection_stop": 25
},
"stoploss": {
"stoploss": -0.189
}
},
"ft_stratparam_v": 1,
"export_time": "2022-01-23 14:20:28.600763+00:00"
}

920
GodStraJD3_6_53_1.py Normal file
View File

@@ -0,0 +1,920 @@
# 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 freqtrade import data
from freqtrade.persistence import Trade
from freqtrade.strategy.parameters import CategoricalParameter, DecimalParameter, IntParameter
from numpy.lib import math
from freqtrade.strategy.interface import IStrategy, SellCheckTuple
from pandas import DataFrame
# --------------------------------
# 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
# TODO: this gene is removed 'MAVP' cuz or error on periods
all_god_genes = {
'Overlap Studies': {
'BBANDS-0', # Bollinger Bands
'BBANDS-1', # Bollinger Bands
'BBANDS-2', # Bollinger Bands
'DEMA', # Double Exponential Moving Average
'EMA', # Exponential Moving Average
'HT_TRENDLINE', # Hilbert Transform - Instantaneous Trendline
'KAMA', # Kaufman Adaptive Moving Average
'MA', # Moving average
'MAMA-0', # MESA Adaptive Moving Average
'MAMA-1', # MESA Adaptive Moving Average
# TODO: Fix this
# 'MAVP', # Moving average with variable period
'MIDPOINT', # MidPoint over period
'MIDPRICE', # Midpoint Price over period
'SAR', # Parabolic SAR
'SAREXT', # Parabolic SAR - Extended
'SMA', # Simple Moving Average
'T3', # Triple Exponential Moving Average (T3)
'TEMA', # Triple Exponential Moving Average
'TRIMA', # Triangular Moving Average
'WMA', # Weighted Moving Average
},
'Momentum Indicators': {
'ADX', # Average Directional Movement Index
'ADXR', # Average Directional Movement Index Rating
'APO', # Absolute Price Oscillator
'AROON-0', # Aroon
'AROON-1', # Aroon
'AROONOSC', # Aroon Oscillator
'BOP', # Balance Of Power
'CCI', # Commodity Channel Index
'CMO', # Chande Momentum Oscillator
'DX', # Directional Movement Index
'MACD-0', # Moving Average Convergence/Divergence
'MACD-1', # Moving Average Convergence/Divergence
'MACD-2', # Moving Average Convergence/Divergence
'MACDEXT-0', # MACD with controllable MA type
'MACDEXT-1', # MACD with controllable MA type
'MACDEXT-2', # MACD with controllable MA type
'MACDFIX-0', # Moving Average Convergence/Divergence Fix 12/26
'MACDFIX-1', # Moving Average Convergence/Divergence Fix 12/26
'MACDFIX-2', # Moving Average Convergence/Divergence Fix 12/26
'MFI', # Money Flow Index
'MINUS_DI', # Minus Directional Indicator
'MINUS_DM', # Minus Directional Movement
'MOM', # Momentum
'PLUS_DI', # Plus Directional Indicator
'PLUS_DM', # Plus Directional Movement
'PPO', # Percentage Price Oscillator
'ROC', # Rate of change : ((price/prevPrice)-1)*100
# Rate of change Percentage: (price-prevPrice)/prevPrice
'ROCP',
'ROCR', # Rate of change ratio: (price/prevPrice)
# Rate of change ratio 100 scale: (price/prevPrice)*100
'ROCR100',
'RSI', # Relative Strength Index
'STOCH-0', # Stochastic
'STOCH-1', # Stochastic
'STOCHF-0', # Stochastic Fast
'STOCHF-1', # Stochastic Fast
'STOCHRSI-0', # Stochastic Relative Strength Index
'STOCHRSI-1', # Stochastic Relative Strength Index
# 1-day Rate-Of-Change (ROC) of a Triple Smooth EMA
'TRIX',
'ULTOSC', # Ultimate Oscillator
'WILLR', # Williams' %R
},
'Volume Indicators': {
'AD', # Chaikin A/D Line
'ADOSC', # Chaikin A/D Oscillator
'OBV', # On Balance Volume
},
'Volatility Indicators': {
'ATR', # Average True Range
'NATR', # Normalized Average True Range
'TRANGE', # True Range
},
'Price Transform': {
'AVGPRICE', # Average Price
'MEDPRICE', # Median Price
'TYPPRICE', # Typical Price
'WCLPRICE', # Weighted Close Price
},
'Cycle Indicators': {
'HT_DCPERIOD', # Hilbert Transform - Dominant Cycle Period
'HT_DCPHASE', # Hilbert Transform - Dominant Cycle Phase
'HT_PHASOR-0', # Hilbert Transform - Phasor Components
'HT_PHASOR-1', # Hilbert Transform - Phasor Components
'HT_SINE-0', # Hilbert Transform - SineWave
'HT_SINE-1', # Hilbert Transform - SineWave
'HT_TRENDMODE', # Hilbert Transform - Trend vs Cycle Mode
},
'Pattern Recognition': {
'CDL2CROWS', # Two Crows
'CDL3BLACKCROWS', # Three Black Crows
'CDL3INSIDE', # Three Inside Up/Down
'CDL3LINESTRIKE', # Three-Line Strike
'CDL3OUTSIDE', # Three Outside Up/Down
'CDL3STARSINSOUTH', # Three Stars In The South
'CDL3WHITESOLDIERS', # Three Advancing White Soldiers
'CDLABANDONEDBABY', # Abandoned Baby
'CDLADVANCEBLOCK', # Advance Block
'CDLBELTHOLD', # Belt-hold
'CDLBREAKAWAY', # Breakaway
'CDLCLOSINGMARUBOZU', # Closing Marubozu
'CDLCONCEALBABYSWALL', # Concealing Baby Swallow
'CDLCOUNTERATTACK', # Counterattack
'CDLDARKCLOUDCOVER', # Dark Cloud Cover
'CDLDOJI', # Doji
'CDLDOJISTAR', # Doji Star
'CDLDRAGONFLYDOJI', # Dragonfly Doji
'CDLENGULFING', # Engulfing Pattern
'CDLEVENINGDOJISTAR', # Evening Doji Star
'CDLEVENINGSTAR', # Evening Star
'CDLGAPSIDESIDEWHITE', # Up/Down-gap side-by-side white lines
'CDLGRAVESTONEDOJI', # Gravestone Doji
'CDLHAMMER', # Hammer
'CDLHANGINGMAN', # Hanging Man
'CDLHARAMI', # Harami Pattern
'CDLHARAMICROSS', # Harami Cross Pattern
'CDLHIGHWAVE', # High-Wave Candle
'CDLHIKKAKE', # Hikkake Pattern
'CDLHIKKAKEMOD', # Modified Hikkake Pattern
'CDLHOMINGPIGEON', # Homing Pigeon
'CDLIDENTICAL3CROWS', # Identical Three Crows
'CDLINNECK', # In-Neck Pattern
'CDLINVERTEDHAMMER', # Inverted Hammer
'CDLKICKING', # Kicking
'CDLKICKINGBYLENGTH', # Kicking - bull/bear determined by the longer marubozu
'CDLLADDERBOTTOM', # Ladder Bottom
'CDLLONGLEGGEDDOJI', # Long Legged Doji
'CDLLONGLINE', # Long Line Candle
'CDLMARUBOZU', # Marubozu
'CDLMATCHINGLOW', # Matching Low
'CDLMATHOLD', # Mat Hold
'CDLMORNINGDOJISTAR', # Morning Doji Star
'CDLMORNINGSTAR', # Morning Star
'CDLONNECK', # On-Neck Pattern
'CDLPIERCING', # Piercing Pattern
'CDLRICKSHAWMAN', # Rickshaw Man
'CDLRISEFALL3METHODS', # Rising/Falling Three Methods
'CDLSEPARATINGLINES', # Separating Lines
'CDLSHOOTINGSTAR', # Shooting Star
'CDLSHORTLINE', # Short Line Candle
'CDLSPINNINGTOP', # Spinning Top
'CDLSTALLEDPATTERN', # Stalled Pattern
'CDLSTICKSANDWICH', # Stick Sandwich
# Takuri (Dragonfly Doji with very long lower shadow)
'CDLTAKURI',
'CDLTASUKIGAP', # Tasuki Gap
'CDLTHRUSTING', # Thrusting Pattern
'CDLTRISTAR', # Tristar Pattern
'CDLUNIQUE3RIVER', # Unique 3 River
'CDLUPSIDEGAP2CROWS', # Upside Gap Two Crows
'CDLXSIDEGAP3METHODS', # Upside/Downside Gap Three Methods
},
'Statistic Functions': {
'BETA', # Beta
'CORREL', # Pearson's Correlation Coefficient (r)
'LINEARREG', # Linear Regression
'LINEARREG_ANGLE', # Linear Regression Angle
'LINEARREG_INTERCEPT', # Linear Regression Intercept
'LINEARREG_SLOPE', # Linear Regression Slope
'STDDEV', # Standard Deviation
'TSF', # Time Series Forecast
'VAR', # Variance
}
}
god_genes = set()
########################### SETTINGS ##############################
# god_genes = {'SMA'}
god_genes |= all_god_genes['Overlap Studies']
god_genes |= all_god_genes['Momentum Indicators']
god_genes |= all_god_genes['Volume Indicators']
god_genes |= all_god_genes['Volatility Indicators']
god_genes |= all_god_genes['Price Transform']
god_genes |= all_god_genes['Cycle Indicators']
god_genes |= all_god_genes['Pattern Recognition']
god_genes |= all_god_genes['Statistic Functions']
#timeperiods = [5, 6, 12, 15, 50, 55, 100, 110]
timeperiods = [5, 10, 20, 50, 100]
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
ind_1 = 'HT_TRENDLINE-100'
ind_2 = 'MACD-1-100'
ind_3 = 'CCI-20'
ind_4 = 'CDLDOJISTAR-10'
ind_5 = 'WCLPRICE-10'
ind_6 = 'DEMA-50'
sell_1 = "CDLLONGLINE-20"
sell_2 = "STOCHF-1-50"
sell_3 = "MACDEXT-0-5"
sell_4 = "MIDPOINT-10"
sell_5 = "CDLTRISTAR-10"
sell_6 = "CDLBELTHOLD-50"
########################### END SETTINGS ##########################
# DATAFRAME = DataFrame()
god_genes = list(god_genes)
# print('selected indicators for optimzatin: \n', god_genes)
god_genes_with_timeperiod = list()
for god_gene in god_genes:
for timeperiod in timeperiods:
# print(f'{god_gene}-{timeperiod}')
god_genes_with_timeperiod.append(f'{god_gene}-{timeperiod}')
# Let give somethings to CatagoricalParam to Play with them
# When just one thing is inside catagorical lists
# TODO: its Not True Way :)
if len(god_genes) == 1:
god_genes = god_genes*2
if len(timeperiods) == 1:
timeperiods = timeperiods*2
if len(operators) == 1:
operators = operators*2
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):
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] > dataframe[crossed_indicator]
)
elif operator == "=":
condition = (
np.isclose(dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "<":
condition = (
dataframe[indicator] < dataframe[crossed_indicator]
)
elif operator == "C":
condition = (
(qtpylib.crossed_below(dataframe[indicator], dataframe[crossed_indicator])) |
(qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator]))
)
elif operator == "CA":
condition = (
qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "CB":
condition = (
qtpylib.crossed_below(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == ">R":
condition = (
dataframe[indicator] > real_num
)
elif operator == "=R":
condition = (
np.isclose(dataframe[indicator], real_num)
)
elif operator == "<R":
condition = (
dataframe[indicator] < real_num
)
elif operator == "/>R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) > real_num
)
elif operator == "/=R":
condition = (
np.isclose(dataframe[indicator].div(
dataframe[crossed_indicator]), real_num)
)
elif operator == "/<R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) < real_num
)
elif operator == "UT":
condition = (
dataframe[indicator] > dataframe[indicator_trend_sma]
)
elif operator == "DT":
condition = (
dataframe[indicator] < dataframe[indicator_trend_sma]
)
elif operator == "OT":
condition = (
np.isclose(dataframe[indicator], dataframe[indicator_trend_sma])
)
elif operator == "CUT":
condition = (
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] > dataframe[indicator_trend_sma]
)
)
elif operator == "CDT":
condition = (
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] < dataframe[indicator_trend_sma]
)
)
elif operator == "COT":
condition = (
(
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) |
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
) &
(
np.isclose(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
)
return condition, dataframe
class GodStraJD3_6_53_1(IStrategy):
# #################### RESULTS PASTE PLACE ####################
# ROI table:
minimal_roi = {
"0": 1,
# "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'},
'sma10': {'color': 'yellow'},
'min': {'color': 'white'},
'max': {'color': 'white'},
'sma20': {'color': 'cyan'}
},
'subplots': {
# Subplots - each dict defines one additional plot
"BB": {
'bb_width': {'color': 'white'},
'bb_min': {'color': 'red'},
},
"Ind": {
ind_1: {'color': 'green'},
ind_2: {'color': 'blue'},
ind_3: {'color': 'red'}
},
"Ind2": {
ind_4: {'color': 'green'},
ind_5: {'color': 'blue'},
ind_6: {'color': 'red'}
},
"Profit": {
'profit': {'color': 'pink'},
},
"Rsi": {
'rsi': {'color': 'pink'},
},
# "rolling": {
# 'bb_rolling': {'color': '#87e470'},
# "bb_rolling_min": {'color': '#ac3e2a'}
# },
"percent": {
"percent": {'color': 'green'},
"percent3": {'color': 'blue'},
"percent5": {'color': 'red'}
}
}
}
# #################### END OF RESULT PLACE ####################
# TODO: Its not dry code!
# Buy Hyperoptable Parameters/Spaces.
buy_crossed_indicator0 = CategoricalParameter(god_genes_with_timeperiod, default="ADD-20", space='buy')
buy_crossed_indicator1 = CategoricalParameter(god_genes_with_timeperiod, default="ASIN-6", space='buy')
buy_crossed_indicator2 = CategoricalParameter(god_genes_with_timeperiod, default="CDLEVENINGSTAR-50", space='buy')
buy_indicator0 = CategoricalParameter(god_genes_with_timeperiod, default="SMA-100", space='buy')
buy_indicator1 = CategoricalParameter(god_genes_with_timeperiod, default="WILLR-50", space='buy')
buy_indicator2 = CategoricalParameter(god_genes_with_timeperiod, default="CDLHANGINGMAN-20", space='buy')
buy_operator0 = CategoricalParameter(operators, default="/<R", space='buy')
buy_operator1 = CategoricalParameter(operators, default="<R", space='buy')
buy_operator2 = CategoricalParameter(operators, default="CB", space='buy')
protection_max_allowed_dd = DecimalParameter(0, 1, decimals=DECIMALS, default=0.04, space='protection')
protection_stop = IntParameter(0, 100, default=48, space='protection')
buy_real_num0 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.89009, space='buy')
buy_real_num1 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.56953, space='buy')
buy_real_num2 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.38365, space='buy')
# Sell Hyperoptable Parameters/Spaces.
sell_crossed_indicator0 = CategoricalParameter(god_genes_with_timeperiod, default="CDLSHOOTINGSTAR-150", space='sell')
sell_crossed_indicator1 = CategoricalParameter(god_genes_with_timeperiod, default="MAMA-1-100", space='sell')
sell_crossed_indicator2 = CategoricalParameter(god_genes_with_timeperiod, default="CDLMATHOLD-6", space='sell')
sell_indicator0 = CategoricalParameter(god_genes_with_timeperiod, default="CDLUPSIDEGAP2CROWS-5", space='sell')
sell_indicator1 = CategoricalParameter(god_genes_with_timeperiod, default="CDLHARAMICROSS-150", space='sell')
sell_indicator2 = CategoricalParameter(god_genes_with_timeperiod, default="CDL2CROWS-5", space='sell')
sell_operator0 = CategoricalParameter(operators, default="<R", space='sell')
sell_operator1 = CategoricalParameter(operators, default="D", space='sell')
sell_operator2 = CategoricalParameter(operators, default="/>R", space='sell')
sell_real_num0 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.09731, space='sell')
sell_real_num1 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.81657, space='sell')
sell_real_num2 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.87267, space='sell')
@property
def protections(self):
return [
{
"method": "CooldownPeriod",
"stop_duration_candles": 10
},
{
"method": "MaxDrawdown",
"lookback_period_candles": 48,
"trade_limit": 2,
"stop_duration_candles": self.protection_stop.value,
"max_allowed_drawdown": self.protection_max_allowed_dd.value,
"only_per_pair": False
},
]
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()
#print("last_candle", last_candle)
#print("previous_last_candle", previous_last_candle)
#dataframe.iloc[-1]['profit'] = current_profit
count = 0
for coin, balance in self.wallets.get_all_balances().items():
count = count + 1
# print(coin, " ", balance)
# print("count=", count)
if (current_profit > 0) \
& ((previous_5_candle['sma10'] > last_candle['sma10'] * 1.002) \
| (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 (current_profit > 0) \
& ((current_time - trade.open_date_utc).seconds >= 3600) \
& ((previous_last_candle['sma20'] > last_candle['sma20']) &
((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 (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['percent'] < 0) & (last_candle['percent3'] < 0)):
# print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
return '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['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 (current_profit > 0) \
& (last_candle['rsi'] > 88): #| (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)):
# print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
return 'over_rsi'
def informative_pairs(self):
return []
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# MACD
# macd = ta.MACD(dataframe)
# dataframe['macd'] = macd['macd']
# dataframe['macdsignal'] = macd['macdsignal']
# dataframe['macdhist'] = macd['macdhist']
# # # Plus Directional Indicator / Movement
# dataframe['plus_dm'] = ta.PLUS_DM(dataframe)
# dataframe['plus_di'] = ta.PLUS_DI(dataframe)
#
# # Minus Directional Indicator / Movement
# dataframe['adx'] = ta.ADX(dataframe)
dataframe[ind_1] = gene_calculator(dataframe, ind_1)
dataframe[ind_2] = gene_calculator(dataframe, ind_2)
dataframe[ind_3] = gene_calculator(dataframe, ind_3)
dataframe[ind_4] = gene_calculator(dataframe, ind_4)
dataframe[ind_5] = gene_calculator(dataframe, ind_5)
dataframe[ind_6] = gene_calculator(dataframe, ind_6)
dataframe[sell_1] = gene_calculator(dataframe, sell_1)
dataframe[sell_2] = gene_calculator(dataframe, sell_2)
dataframe[sell_3] = gene_calculator(dataframe, sell_3)
dataframe[sell_4] = gene_calculator(dataframe, sell_4)
dataframe[sell_5] = gene_calculator(dataframe, sell_5)
dataframe[sell_6] = gene_calculator(dataframe, sell_6)
# dataframe['MINUS_DM-5'] = ta.MINUS_DM(dataframe, timeperiod=5)
# dataframe['LINEARREG-50'] = ta.LINEARREG(dataframe, timeperiod=50)
# dataframe['MA-20'] = ta.MA(dataframe, timeperiod=20)
# stoch = ta.STOCH(dataframe, timeperiod=10)
# # print(stoch)
# dataframe['STOCH-1-10'] = stoch['slowd']
# dataframe['CDLDRAGONFLYDOJI-5'] = ta.CDLDRAGONFLYDOJI(dataframe, timeperiod=5)
# dataframe['minus_di'] = ta.MINUS_DI(dataframe)
# dataframe['min'] = ta.MIN(dataframe)
# dataframe['max'] = ta.MAX(dataframe)
# # Aroon, Aroon Oscillator
# aroon = ta.AROON(dataframe)
# dataframe['aroonup'] = aroon['aroonup']
# dataframe['aroondown'] = aroon['aroondown']
# dataframe['aroonosc'] = ta.AROONOSC(dataframe)
dataframe['profit'] = 0
# RSI
dataframe['rsi'] = ta.RSI(dataframe)
# # EMA - Exponential Moving Average
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
# dataframe['ema5'] = ta.EMA(dataframe, timeperiod=5)
# dataframe['ema10'] = ta.EMA(dataframe, timeperiod=10)
# dataframe['ema21'] = ta.EMA(dataframe, timeperiod=21)
# dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50)
# dataframe['ema100'] = ta.EMA(dataframe, timeperiod=100)
# # SMA - Simple Moving Average
# dataframe['sma3'] = ta.SMA(dataframe, timeperiod=3)
# 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['sma200'] = ta.SMA(dataframe, timeperiod=200)
# dataframe['sma200_95'] = ta.SMA(dataframe, timeperiod=200) * 0.95
# dataframe['sma200_98'] = ta.SMA(dataframe, timeperiod=200) * 0.98
# dataframe['sma500'] = ta.SMA(dataframe, timeperiod=500)
# dataframe['sma500_90'] = ta.SMA(dataframe, timeperiod=500) * 0.9
# dataframe['sma500_95'] = ta.SMA(dataframe, timeperiod=500) * 0.95
# dataframe['sma500_20'] = ta.SMA(dataframe, timeperiod=500) * 0.2
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['min'] = ta.MIN(dataframe['close'], timeperiod=200)
dataframe['min20'] = ta.MIN(dataframe['close'], timeperiod=20)
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_min'] = ta.MIN(dataframe['bb_lowerband'], timeperiod=36)
# 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"]
# )
# # EMA - Exponential Moving Average
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = list()
# TODO: Its not dry code!
buy_indicator = self.buy_indicator0.value
buy_crossed_indicator = self.buy_crossed_indicator0.value
buy_operator = self.buy_operator0.value
buy_real_num = self.buy_real_num0.value
condition, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition)
# backup
buy_indicator = self.buy_indicator1.value
buy_crossed_indicator = self.buy_crossed_indicator1.value
buy_operator = self.buy_operator1.value
buy_real_num = self.buy_real_num1.value
condition, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition)
buy_indicator = self.buy_indicator2.value
buy_crossed_indicator = self.buy_crossed_indicator2.value
buy_operator = self.buy_operator2.value
buy_real_num = self.buy_real_num2.value
condition, dataframe = condition_generator(
dataframe,
buy_operator,
buy_indicator,
buy_crossed_indicator,
buy_real_num
)
conditions.append(condition)
if conditions:
dataframe.loc[
(
(dataframe['close'].shift(2) < dataframe['bb_lowerband'].shift(2))
& (dataframe['bb_width'].shift(2) >= 0.12)
& (dataframe['volume'].shift(2) * dataframe['close'].shift(2) / 1000 > 100)
) | (
(reduce(lambda x, y: x & y, conditions))
& (dataframe['volume10'] * dataframe['close'] / 1000 >= 100)
& (dataframe['close'] < dataframe['sma20'])
& (dataframe['close'] < dataframe['sma50'])
# & (dataframe['sma10'].shift(1) <= dataframe['sma10'])
# (dataframe['close'] * 0.99 < dataframe['bb_lowerband'])
# (dataframe['rsi'] < 45)
),
'buy']=1
# print(len(dataframe.keys()))
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = list()
# TODO: Its not dry code!
sell_indicator = self.sell_indicator0.value
sell_crossed_indicator = self.sell_crossed_indicator0.value
sell_operator = self.sell_operator0.value
sell_real_num = self.sell_real_num0.value
condition, dataframe = condition_generator(
dataframe,
sell_operator,
sell_indicator,
sell_crossed_indicator,
sell_real_num
)
conditions.append(condition)
sell_indicator = self.sell_indicator1.value
sell_crossed_indicator = self.sell_crossed_indicator1.value
sell_operator = self.sell_operator1.value
sell_real_num = self.sell_real_num1.value
condition, dataframe = condition_generator(
dataframe,
sell_operator,
sell_indicator,
sell_crossed_indicator,
sell_real_num
)
conditions.append(condition)
sell_indicator = self.sell_indicator2.value
sell_crossed_indicator = self.sell_crossed_indicator2.value
sell_operator = self.sell_operator2.value
sell_real_num = self.sell_real_num2.value
condition, dataframe = condition_generator(
dataframe,
sell_operator,
sell_indicator,
sell_crossed_indicator,
sell_real_num
)
conditions.append(condition)
#dataframe.loc[(dataframe['close'] < dataframe['bb_lowerband']),'sell']=1
# count = 0
# for coin, balance in self.wallets.get_all_balances().items():
# count = count + 1
# # print(coin, " ", balance)
# if (count == self.config['max_open_trades']) & (current_profit < -0.04) \
# & ((current_time - trade.open_date_utc).seconds >= 3600 * 6):
# self.lock_pair(pair, until=current_time + timedelta(hours=10))
# print("stop_short_loss", pair, trade, " profit=", current_profit, " rate=", current_rate,
# "count=", count, "max=", self.config['max_open_trades'])
# return 'stop_short_loss'
# print("sell pair=", self.wallets.get_all_balances()[metadata['pair']])
# if conditions:
# dataframe.loc[
# (
# reduce(lambda x, y: x & y, conditions) #(dataframe['percent3'] > 0)
# # | (dataframe['percent3'] < -0.03)
# ),
# 'sell']=1
dataframe.loc[
(
(dataframe['close'] < dataframe['open']) &
(dataframe['close'].shift(1) < dataframe['open'].shift(1)) &
(dataframe['close'].shift(2) < dataframe['open'].shift(2)) &
(dataframe['close'] < dataframe['bb_lowerband']) &
(((dataframe['bb_lowerband'].shift(2) - dataframe['bb_lowerband']) / dataframe['bb_lowerband']) >= 0.02)
# (((dataframe['close'].shift(1) - dataframe['close']) / dataframe['close']) >= 0.025)
), 'sell'] = 1
return dataframe

29
GodStraJD3_6_53_2.json Normal file
View File

@@ -0,0 +1,29 @@
{
"strategy_name": "GodStraJD3_6_53_2",
"params": {
"roi": {
"0": 2
},
"stoploss": {
"stoploss": -0.02
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.15,
"trailing_stop_positive_offset": 0.2,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_real_num0": 0.87,
"buy_real_num1": 0.33,
"buy_real_num2": 0.89
},
"sell": {},
"protection": {
"protection_max_allowed_dd": 0.04,
"protection_stop": 288
}
},
"ft_stratparam_v": 1,
"export_time": "2022-01-23 13:16:55.016896+00:00"
}

520
GodStraJD3_6_53_2.py Normal file
View File

@@ -0,0 +1,520 @@
# 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 freqtrade import data
from freqtrade.persistence import Trade
from freqtrade.strategy.parameters import CategoricalParameter, DecimalParameter, IntParameter
from numpy.lib import math
from freqtrade.strategy.interface import IStrategy
from pandas import DataFrame
# --------------------------------
# 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
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_crossed_indicator1 = 'DX-5'
buy_crossed_indicator2 = 'LINEARREG-50'
buy_indicator0 = 'MA-20'
buy_indicator1 = 'STOCH-1-10'
buy_indicator2 = 'CDLDRAGONFLYDOJI-5'
buy_operator0 = "/<R"
buy_operator1 = ">"
buy_operator2 = "/<R"
# buy_real_num0 = 0.1,
# buy_real_num1 = 0.0,
# buy_real_num2 = 0.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):
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] > dataframe[crossed_indicator]
)
elif operator == "=":
condition = (
np.isclose(dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "<":
condition = (
dataframe[indicator] < dataframe[crossed_indicator]
)
elif operator == "C":
condition = (
(qtpylib.crossed_below(dataframe[indicator], dataframe[crossed_indicator])) |
(qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator]))
)
elif operator == "CA":
condition = (
qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "CB":
condition = (
qtpylib.crossed_below(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == ">R":
condition = (
dataframe[indicator] > real_num
)
elif operator == "=R":
condition = (
np.isclose(dataframe[indicator], real_num)
)
elif operator == "<R":
condition = (
dataframe[indicator] < real_num
)
elif operator == "/>R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) > real_num
)
elif operator == "/=R":
condition = (
np.isclose(dataframe[indicator].div(
dataframe[crossed_indicator]), real_num)
)
elif operator == "/<R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) < real_num
)
elif operator == "UT":
condition = (
dataframe[indicator] > dataframe[indicator_trend_sma]
)
elif operator == "DT":
condition = (
dataframe[indicator] < dataframe[indicator_trend_sma]
)
elif operator == "OT":
condition = (
np.isclose(dataframe[indicator], dataframe[indicator_trend_sma])
)
elif operator == "CUT":
condition = (
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] > dataframe[indicator_trend_sma]
)
)
elif operator == "CDT":
condition = (
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] < dataframe[indicator_trend_sma]
)
)
elif operator == "COT":
condition = (
(
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) |
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
) &
(
np.isclose(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
)
return condition, dataframe
class GodStraJD3_6_53_2(IStrategy):
# #################### RESULTS PASTE PLACE ####################
# ROI table:
minimal_roi = {
"0": 2,
# "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'},
'sma10': {'color': 'yellow'},
'min': {'color': 'white'},
'max': {'color': 'white'},
'sma20': {'color': 'cyan'}
},
'subplots': {
# Subplots - each dict defines one additional plot
"BB": {
'bb_width': {'color': 'white'},
'bb_min': {'color': 'red'},
},
"Ind0": {
buy_crossed_indicator0: {'color': 'green'},
buy_indicator0: {'color': 'red'}
},
"Ind1": {
buy_indicator1: {'color': 'yellow'},
buy_crossed_indicator1: {'color': 'pink'}
},
"Ind2": {
buy_indicator2: {'color': 'cyan'},
buy_crossed_indicator2: {'color': 'blue'},
},
"Rsi": {
'rsi': {'color': 'pink'},
},
# "rolling": {
# 'bb_rolling': {'color': '#87e470'},
# "bb_rolling_min": {'color': '#ac3e2a'}
# },
"percent": {
"percent": {'color': 'green'},
"percent3": {'color': 'blue'},
"percent5": {'color': 'red'}
}
}
}
# #################### END OF RESULT PLACE ####################
# TODO: Its not dry code!
# Buy Hyperoptable Parameters/Spaces.
buy_real_num0 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.1, space='buy')
buy_real_num1 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.0, space='buy')
buy_real_num2 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.5, space='buy')
protection_max_allowed_dd = DecimalParameter(0, 1, decimals=DECIMALS, default=0.04, space='protection')
protection_stop = IntParameter(0, 100, default=48, space='protection')
@property
def protections(self):
return [
{
"method": "CooldownPeriod",
"stop_duration_candles": 10
},
{
"method": "MaxDrawdown",
"lookback_period_candles": 48,
"trade_limit": 2,
"stop_duration_candles": self.protection_stop.value,
"max_allowed_drawdown": self.protection_max_allowed_dd.value,
"only_per_pair": False
},
]
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 (current_profit > 0) \
& ((previous_5_candle['sma10'] > last_candle['sma10'] * 1.005) \
| (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 (current_profit > 0.01) \
& ((previous_5_candle['sma20'] > last_candle['sma20']) &
((last_candle['percent10'] < -0.01) | (last_candle['percent20'] < -0.01))):
# print("over_bb_band_sma10_desc", pair, trade, " profit=", current_profit, " rate=", current_rate)
return 'sma20'
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.0105)) \
& ((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 (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 (current_profit > 0) \
& (last_candle['rsi'] > 88): #| (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) \
# & (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):
return []
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe[buy_crossed_indicator0] = gene_calculator(dataframe, buy_crossed_indicator0)
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[buy_crossed_indicator1] = gene_calculator(dataframe, buy_crossed_indicator1)
dataframe['profit'] = 0
# RSI
dataframe['rsi'] = ta.RSI(dataframe)
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['min'] = ta.MIN(dataframe['close'], timeperiod=200)
dataframe['min20'] = ta.MIN(dataframe['close'], timeperiod=20)
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_min'] = ta.MIN(dataframe['bb_lowerband'], timeperiod=36)
# 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"]
)
# # EMA - Exponential Moving Average
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = list()
condition, dataframe = condition_generator(
dataframe,
buy_operator0,
buy_indicator0,
buy_crossed_indicator0,
self.buy_real_num0.value
)
conditions.append(condition)
# backup
condition, dataframe = condition_generator(
dataframe,
buy_operator1,
buy_indicator1,
buy_crossed_indicator1,
self.buy_real_num1.value
)
conditions.append(condition)
condition, dataframe = condition_generator(
dataframe,
buy_operator2,
buy_indicator2,
buy_crossed_indicator2,
self.buy_real_num2.value
)
conditions.append(condition)
if conditions:
dataframe.loc[
(
(reduce(lambda x, y: x & y, conditions)) &
(dataframe['volume10'] * dataframe['close'] / 1000 >= 10)
# (dataframe['rsi'] < 45)
),
'buy'] = 1
# print(len(dataframe.keys()))
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
return dataframe

33
GodStraJD3_7.json Normal file
View File

@@ -0,0 +1,33 @@
{
"strategy_name": "GodStraJD3_7",
"params": {
"roi": {
"0": 10
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.15,
"trailing_stop_positive_offset": 0.2,
"trailing_only_offset_is_reached": true
},
"buy": {
"profit_no_change": false,
"profit_old_sma10": false,
"profit_over_rsi": true,
"profit_quick_gain": false,
"profit_quick_gain_3": false,
"profit_quick_lost": true,
"profit_short_loss": true,
"profit_sma10": false,
"profit_sma20": true,
"profit_very_old_sma10": true
},
"sell": {},
"protection": {}
},
"ft_stratparam_v": 1,
"export_time": "2022-02-04 20:21:28.189888+00:00"
}

636
GodStraJD3_7.py Normal file
View File

@@ -0,0 +1,636 @@
# 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 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
# --------------------------------
# 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
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'
# "buy_real_num0": 0.46,
# "buy_real_num1": 0.48,
# "buy_real_num2": 0.67
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):
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] > dataframe[crossed_indicator]
)
elif operator == "=":
condition = (
np.isclose(dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "<":
condition = (
dataframe[indicator] < dataframe[crossed_indicator]
)
elif operator == "C":
condition = (
(qtpylib.crossed_below(dataframe[indicator], dataframe[crossed_indicator])) |
(qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator]))
)
elif operator == "CA":
condition = (
qtpylib.crossed_above(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == "CB":
condition = (
qtpylib.crossed_below(
dataframe[indicator], dataframe[crossed_indicator])
)
elif operator == ">R":
condition = (
dataframe[indicator] > real_num
)
elif operator == "=R":
condition = (
np.isclose(dataframe[indicator], real_num)
)
elif operator == "<R":
condition = (
dataframe[indicator] < real_num
)
elif operator == "/>R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) > real_num
)
elif operator == "/=R":
condition = (
np.isclose(dataframe[indicator].div(
dataframe[crossed_indicator]), real_num)
)
elif operator == "/<R":
condition = (
dataframe[indicator].div(dataframe[crossed_indicator]) < real_num
)
elif operator == "UT":
condition = (
dataframe[indicator] > dataframe[indicator_trend_sma]
)
elif operator == "DT":
condition = (
dataframe[indicator] < dataframe[indicator_trend_sma]
)
elif operator == "OT":
condition = (
np.isclose(dataframe[indicator], dataframe[indicator_trend_sma])
)
elif operator == "CUT":
condition = (
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] > dataframe[indicator_trend_sma]
)
)
elif operator == "CDT":
condition = (
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) &
(
dataframe[indicator] < dataframe[indicator_trend_sma]
)
)
elif operator == "COT":
condition = (
(
(
qtpylib.crossed_below(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
) |
(
qtpylib.crossed_above(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
) &
(
np.isclose(
dataframe[indicator],
dataframe[indicator_trend_sma]
)
)
)
return condition, dataframe
class GodStraJD3_7(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'},
'sma10': {'color': 'yellow'},
# 'min': {'color': 'white'},
# 'max': {'color': 'white'},
'sma20': {'color': 'cyan'}
},
'subplots': {
# Subplots - each dict defines one additional plot
"BB": {
'bb_width': {'color': 'white'},
'bb_min': {'color': 'red'},
},
"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'},
},
# "rolling": {
# 'bb_rolling': {'color': '#87e470'},
# "bb_rolling_min": {'color': '#ac3e2a'}
# },
# "percent": {
# "percent": {'color': 'green'},
# "percent3": {'color': 'blue'},
# "percent5": {'color': 'red'}
# }
}
}
# #################### END OF RESULT PLACE ####################
# TODO: Its not dry code!
# Buy Hyperoptable Parameters/Spaces.
# "buy_real_num0": 0.46,
# "buy_real_num1": 0.48,
# "buy_real_num2": 0.67
#
# buy_real_num0 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.46, space='buy')
# buy_real_num1 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.48, space='buy')
# buy_real_num2 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.67, space='buy')
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")
# protection_max_allowed_dd = DecimalParameter(0, 1, decimals=DECIMALS, default=0.04, space='protection')
# protection_stop = IntParameter(0, 100, default=48, space='protection')
# protection_stoploss_stop = IntParameter(0, 100, default=48, space='protection')
# lookback = IntParameter(0, 200, default=48, space='protection')
# trade_limit = IntParameter(0, 10, default=2, space='protection')
#
# @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
# }
# ]
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 self.profit_quick_lost.value:
if (current_profit >= 0) & (last_candle['percent3'] < -0.01):
return "quick_lost"
if self.profit_no_change.value:
if (current_profit > 0.005) & (last_candle['percent10'] < 0.001):
return "no_change"
#if (current_profit > 0.01) & (last_candle['rsi'] < 30):
# return "small_rsi"
if self.profit_quick_gain_3.value:
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.value:
if (0.01 < current_profit < 0.03) & (last_candle['percent3'] < 0): #& ((current_time - trade.open_date_utc).seconds <= 3600)
return "quick_gain"
if self.profit_sma10.value:
if (current_profit > 0.01) \
& ((previous_5_candle['sma10'] > last_candle['sma10'] * 1.005) \
| (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.value:
if (current_profit > 0.005) & (last_candle['percent5'] < 0) \
& ((current_time - trade.open_date_utc).seconds >= 3600) \
& ((previous_last_candle['sma20'] > last_candle['sma20']) &
((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.value:
# 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.value:
# 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.value:
if (current_profit > 0) \
& (last_candle['rsi'] > 88): #| (previous_last_candle['rsi'] > 75 & last_candle['rsi'] < 70)):
# print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
return 'over_rsi'
if self.profit_short_loss.value:
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):
return []
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe['profit'] = 0
# RSI
dataframe['rsi'] = ta.RSI(dataframe)
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['min'] = ta.MIN(dataframe['close'], timeperiod=200)
dataframe['min20'] = ta.MIN(dataframe['close'], timeperiod=20)
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_min'] = ta.MIN(dataframe['bb_lowerband'], timeperiod=36)
# 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])
# # EMA - Exponential Moving Average
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = list()
condition1, dataframe = condition_generator(
dataframe,
buy_operator0,
buy_indicator0,
buy_crossed_indicator0,
0.7 #self.buy_real_num0.value
)
conditions.append(condition1)
# # backup
# condition2, dataframe = condition_generator(
# dataframe,
# buy_operator1,
# buy_indicator1,
# buy_crossed_indicator1,
# self.buy_real_num1.value
# )
# conditions.append(condition2)
#
# condition3, dataframe = condition_generator(
# dataframe,
# buy_operator2,
# buy_indicator2,
# buy_crossed_indicator2,
# self.buy_real_num2.value
# )
# conditions.append(condition3)
if conditions:
dataframe.loc[
(
reduce(lambda x, y: x & y, conditions)
& (dataframe['volume10'] * dataframe['close'] / 1000 >= 10)
& (dataframe['close'] < dataframe['sma10'])
& (dataframe['open'] < dataframe['sma10'])
& (dataframe['low'] < dataframe['min20'])
# ) | (
# (dataframe['volume10'] * dataframe['close'] / 1000 >= 10)
# & (dataframe['percent20'] < -0.01)
# & (dataframe['percent3'] > 0)
# & (dataframe['close'] < dataframe['sma10'])
# & (dataframe['sma100'].shift(1) < dataframe['sma100'])
#
# ) | (
# (dataframe['volume10'].shift(1) * dataframe['close'].shift(1) / 1000 >= 10)
# & (dataframe['percent20'].shift(1) < -0.01)
# & (dataframe['percent3'].shift(1) > 0)
# & (dataframe['close'].shift(1) < dataframe['sma10'].shift(1))
# & (dataframe['sma100'].shift(1) < dataframe['sma100'])
# # & (dataframe['pente5'].shift(1) > 0)
), 'buy'] = 1
pandas.set_option('display.max_rows', dataframe.shape[0] + 1)
pandas.set_option('display.max_columns', 30)
# print(condition1)
# print(reduce(lambda x, y: x & y, conditions))
# print(reduce(lambda x, y: x & y, condition1), " ",
# reduce(lambda x, y: x & y, condition2), " ",
# reduce(lambda x, y: x & y, condition3), " ",
# # (reduce(lambda x, y: x & y, conditions))
# dataframe['buy'],
#
# )
# if conditions:
# dataframe.loc[
# (
# reduce(lambda x, y: x & y, conditions)
# # & (dataframe['volume10'] * dataframe['close'] / 1000 >= 100)
# # & (dataframe['percent5'] < 0.025)
# # (dataframe['percent10'] < 0.04)
# # ) | (
# # (dataframe['volume10'] * dataframe['close'] / 1000 >= 100)
# # & (dataframe['percent50'] < -0.06)
# # & (dataframe['percent3'] > 0)
# # # & (dataframe['sma10'].shift(12) > dataframe['sma10'].shift(2))
# # & (dataframe['sma10'].shift(2) > dataframe['sma10'].shift(1))
# # & (dataframe['sma10'].shift(1) < dataframe['sma10'])
# # # & (dataframe['sma100'].shift(1) < dataframe['sma100'])
# )
# #(dataframe['percent3'] > 0))
# ,'buy']=1
# print(len(dataframe.keys()))
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
return dataframe

31
GodStraJD3_7_1.json Normal file
View File

@@ -0,0 +1,31 @@
{
"strategy_name": "GodStraJD3_7_1",
"params": {
"roi": {
"0": 10
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.15,
"trailing_stop_positive_offset": 0.2,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_real_num0": 0.5,
"buy_signal_bb_width": 0.029
},
"sell": {},
"protection": {
"lookback": 124,
"protection_max_allowed_dd": 0.85,
"protection_stop": 26,
"protection_stoploss_stop": 91,
"trade_limit": 3
}
},
"ft_stratparam_v": 1,
"export_time": "2022-02-18 23:22:31.726399+00:00"
}

540
GodStraJD3_7_1.py Normal file
View File

@@ -0,0 +1,540 @@
# 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 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
# --------------------------------
# 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
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'
# "buy_real_num0": 0.46,
# "buy_real_num1": 0.48,
# "buy_real_num2": 0.67
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):
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] > dataframe[crossed_indicator])
elif operator == "=":
condition = (np.isclose(dataframe[indicator], dataframe[crossed_indicator]))
elif operator == "<":
condition = (dataframe[indicator] < dataframe[crossed_indicator])
elif operator == "C":
condition = (
(qtpylib.crossed_below(dataframe[indicator], dataframe[crossed_indicator])) |
(qtpylib.crossed_above(dataframe[indicator], dataframe[crossed_indicator]))
)
elif operator == "CA":
condition = (qtpylib.crossed_above(dataframe[indicator], dataframe[crossed_indicator]))
elif operator == "CB":
condition = (qtpylib.crossed_below(dataframe[indicator], dataframe[crossed_indicator]))
elif operator == ">R":
condition = (dataframe[indicator] > real_num)
elif operator == "=R":
condition = (np.isclose(dataframe[indicator], real_num))
elif operator == "<R":
condition = (dataframe[indicator] < real_num)
elif operator == "/>R":
condition = (dataframe[indicator].div(dataframe[crossed_indicator]) > real_num)
elif operator == "/=R":
condition = (np.isclose(dataframe[indicator].div(dataframe[crossed_indicator]), real_num))
elif operator == "/<R":
condition = (dataframe[indicator].div(dataframe[crossed_indicator]) < real_num)
elif operator == "UT":
condition = (dataframe[indicator] > dataframe[indicator_trend_sma])
elif operator == "DT":
condition = (dataframe[indicator] < dataframe[indicator_trend_sma])
elif operator == "OT":
condition = (np.isclose(dataframe[indicator], dataframe[indicator_trend_sma]))
elif operator == "CUT":
condition = (
(
qtpylib.crossed_above(dataframe[indicator], dataframe[indicator_trend_sma])
) &
(
dataframe[indicator] > dataframe[indicator_trend_sma]
)
)
elif operator == "CDT":
condition = (
(
qtpylib.crossed_below(dataframe[indicator], dataframe[indicator_trend_sma])
) &
(
dataframe[indicator] < dataframe[indicator_trend_sma]
)
)
elif operator == "COT":
condition = (
(
(
qtpylib.crossed_below(dataframe[indicator], dataframe[indicator_trend_sma])
) |
(
qtpylib.crossed_above(dataframe[indicator], dataframe[indicator_trend_sma])
)
) &
(
np.isclose(dataframe[indicator], dataframe[indicator_trend_sma])
)
)
return condition, dataframe
class GodStraJD3_7_1(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'},
'sma10': {'color': 'yellow'},
# 'min': {'color': 'white'},
# 'max': {'color': 'white'},
'sma20': {'color': 'cyan'}
},
'subplots': {
# Subplots - each dict defines one additional plot
"BB": {
'bb_width': {'color': 'white'},
'bb_min': {'color': 'red'},
},
"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'},
},
# "rolling": {
# 'bb_rolling': {'color': '#87e470'},
# "bb_rolling_min": {'color': '#ac3e2a'}
# },
# "percent": {
# "percent": {'color': 'green'},
# "percent3": {'color': 'blue'},
# "percent5": {'color': 'red'}
# }
}
}
# #################### END OF RESULT PLACE ####################
# TODO: Its not dry code!
# Buy Hyperoptable Parameters/Spaces.
# "buy_real_num0": 0.46,
# "buy_real_num1": 0.48,
# "buy_real_num2": 0.67
#
# buy_real_num0 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.46, space='buy')
# buy_real_num1 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.48, space='buy')
# buy_real_num2 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.67, space='buy')
profit_no_change = False
profit_old_sma10 = False
profit_over_rsi = True
profit_quick_gain = True
profit_quick_gain_3 = True
profit_quick_lost = True
profit_short_loss = True
profit_sma10 = False
profit_sma20 = True
profit_very_old_sma10 = False
# 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, 0.15, decimals=3, default=0.05, space='buy')
buy_real_num0 = DecimalParameter(0, 1, decimals=2, default=0.67, 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')
@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
}
]
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 self.profit_quick_lost:
if (current_profit >= 0) & (last_candle['percent3'] < -0.01):
return "quick_lost"
if self.profit_no_change:
if (current_profit > 0.005) & (last_candle['percent10'] < 0.001) & (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 self.profit_sma10:
if (current_profit > 0.01) \
& ((previous_5_candle['sma10'] > last_candle['sma10'] * 1.005) \
| (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) & (last_candle['percent5'] < 0) \
& ((current_time - trade.open_date_utc).seconds >= 3600) \
& ((previous_last_candle['sma20'] > last_candle['sma20']) &
((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'] > 88): # & (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 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):
return []
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe['profit'] = 0
# RSI
dataframe['rsi'] = ta.RSI(dataframe)
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['min'] = ta.MIN(dataframe['close'], timeperiod=200)
dataframe['min20'] = ta.MIN(dataframe['close'], timeperiod=20)
dataframe['min50'] = ta.MIN(dataframe['close'], timeperiod=50)
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_min'] = ta.MIN(dataframe['bb_lowerband'], timeperiod=36)
# 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])
# # EMA - Exponential Moving Average
# dataframe['ema3'] = ta.EMA(dataframe, timeperiod=3)
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = list()
condition1, dataframe = condition_generator(
dataframe,
buy_operator0,
buy_indicator0,
buy_crossed_indicator0,
self.buy_real_num0.value
)
conditions.append(condition1)
if conditions:
dataframe.loc[
(
reduce(lambda x, y: x & y, conditions)
& (dataframe['volume10'] * dataframe['close'] / 1000 >= 10)
& (dataframe['close'] < dataframe['sma10'])
& (dataframe['open'] < dataframe['sma10'])
& (dataframe['low'] < dataframe['min50'])
& (dataframe['bb_width'] > self.buy_signal_bb_width.value)
), 'buy'] = 1
pandas.set_option('display.max_rows', dataframe.shape[0] + 1)
pandas.set_option('display.max_columns', 30)
# print(condition1)
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
return dataframe

32
GodStraJD3_7_2.json Normal file
View File

@@ -0,0 +1,32 @@
{
"strategy_name": "GodStraJD3_7_2",
"params": {
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": true,
"trailing_stop_positive": 0.042,
"trailing_stop_positive_offset": 0.119,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_decalage0": 6,
"buy_real_num0": 0.9,
"buy_signal_bb_width": 0.0
},
"sell": {},
"protection": {
"lookback": 133,
"protection_max_allowed_dd": 0.71,
"protection_stop": 61,
"protection_stoploss_stop": 50,
"trade_limit": 9
},
"roi": {
"0": 2
}
},
"ft_stratparam_v": 1,
"export_time": "2022-03-07 17:59:59.847942+00:00"
}

606
GodStraJD3_7_2.py Normal file
View File

@@ -0,0 +1,606 @@
# 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 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
# --------------------------------
# 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
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'
# "buy_real_num0": 0.46,
# "buy_real_num1": 0.48,
# "buy_real_num2": 0.67
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_2(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'},
'sma10': {'color': 'yellow'},
'min20': {'color': '#87e470'},
'min50': {'color': '#ac3e2a'},
"min1.1": {'color': 'yellow'},
'sma20': {'color': 'cyan'}
},
'subplots': {
# Subplots - each dict defines one additional plot
"BB": {
'bb_width': {'color': 'white'}
},
# "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": {
'ecart_20': {'color': 'red'},
'ecart_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 ####################
# TODO: Its not dry code!
# Buy Hyperoptable Parameters/Spaces.
# "buy_real_num0": 0.46,
# "buy_real_num1": 0.48,
# "buy_real_num2": 0.67
#
# buy_real_num0 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.46, space='buy')
# buy_real_num1 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.48, space='buy')
# buy_real_num2 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.67, space='buy')
profit_no_change = False
profit_old_sma10 = False
profit_over_rsi = True
profit_quick_gain = True
profit_quick_gain_3 = True
profit_quick_lost = False
profit_short_loss = False
profit_sma10 = False
profit_sma20 = True
profit_very_old_sma10 = False
# 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, 0.15, decimals=2, default=0.05, space='buy')
buy_real_num0 = DecimalParameter(0, 1, decimals=2, default=0.67, space='buy')
buy_decalage0 = IntParameter(1, 10, default=5, 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')
@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
}
]
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 (current_profit >= -0.01) & ((current_time - trade.open_date_utc).days >= 5) \
& ((current_time - trade.open_date_utc).days < 10) \
& (previous_last_candle['sma20'] > last_candle['sma20']):
return "too_old_0.01"
if (current_profit >= -0.02) & ((current_time - trade.open_date_utc).days >= 10) \
& ((current_time - trade.open_date_utc).days < 15) \
& (previous_last_candle['sma20'] > last_candle['sma20']):
return "too_old_0.02"
if (current_profit >= -0.03) & ((current_time - trade.open_date_utc).days >= 15) \
& (previous_last_candle['sma20'] > last_candle['sma20']):
return "too_old_0.03"
if self.profit_quick_lost:
if (current_profit >= 0) & (last_candle['percent3'] < -0.015):
return "quick_lost"
if self.profit_no_change:
if (current_profit > 0.005) & (last_candle['percent10'] < 0.001) & (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 self.profit_sma10:
if (current_profit > 0.01) \
& ((previous_5_candle['sma10'] > last_candle['sma10'] * 1.005) \
| (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) & (last_candle['percent5'] < 0) \
& ((current_time - trade.open_date_utc).seconds >= 3600) \
& ((previous_last_candle['sma20'] > last_candle['sma20']) &
((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'] > 88) & ( \
(last_candle['percent'] < - current_profit / 3) |
(last_candle['percent3'] < - current_profit / 3)):
# print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
return 'over_rsi'
if False & (current_profit > 0) & (last_candle[
'rsi'] > 88): # & (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 False & (current_profit > 0) & (previous_last_candle['rsi'] > 82) & (
last_candle['percent'] < -0.02): # | (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):
return []
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# dataframe['profit'] = 0
# RSI
dataframe['rsi'] = ta.RSI(dataframe)
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=72)
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["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_min'] = ta.MIN(dataframe['bb_lowerband'], timeperiod=36)
dataframe['distance_min'] = (dataframe['close'] - dataframe['min']) / dataframe['close']
dataframe['min1.1'] = 1.01 * dataframe['min']
# 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)
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
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)
if conditions:
for decalage in range(3, self.buy_decalage0.value):
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['min50'].shift(decalage) == dataframe['min50'])
& (dataframe['min10'] <= dataframe['min50'] * 1.02)
& (dataframe['percent20'].shift(decalage) <= -0.01)
# & (dataframe['min20'] == dataframe['min50'])
), ['buy', 'buy_tag']] = (1, 'buy_1_' + str(decalage))
dataframe.loc[
(
(dataframe['cond1'].shift(decalage) <= 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['sma10'])
& (dataframe['min50'].shift(decalage) == dataframe['min50'])
# & (dataframe['min10'] <= dataframe['min50'] * 1.02)
& (dataframe['percent20'].shift(decalage) <= -0.02)
# & (dataframe['min20'] == dataframe['min50'])
), ['buy', 'buy_tag']] = (1, 'buy_2_' + str(decalage))
# pandas.set_option('display.max_rows', dataframe.shape[0] + 1)
# pandas.set_option('display.max_columns', 30)
# print(condition1)
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
return dataframe

34
GodStraJD3_7_3.json Normal file
View File

@@ -0,0 +1,34 @@
{
"strategy_name": "GodStraJD3_7_3",
"params": {
"roi": {
"0": 10
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.15,
"trailing_stop_positive_offset": 0.2,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_decalage0": 6,
"buy_real_num0": 0.9,
"buy_decalage2": 5,
"buy_real_num2": 1.5,
"buy_signal_bb_width": 0.06
},
"sell": {},
"protection": {
"lookback": 133,
"protection_max_allowed_dd": 0.71,
"protection_stop": 61,
"protection_stoploss_stop": 50,
"trade_limit": 9
}
},
"ft_stratparam_v": 1,
"export_time": "2022-02-25 21:24:08.672826+00:00"
}

641
GodStraJD3_7_3.py Normal file
View File

@@ -0,0 +1,641 @@
# 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 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
# --------------------------------
# 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
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'
# "buy_real_num0": 0.46,
# "buy_real_num1": 0.48,
# "buy_real_num2": 0.67
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_3(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'},
'sma10': {'color': 'yellow'},
'min20': {'color': '#87e470'},
'min50': {'color': '#ac3e2a'},
"min1.1": {'color': 'yellow'},
'sma20': {'color': 'cyan'}
},
'subplots': {
# Subplots - each dict defines one additional plot
"BB": {
'bb_width': {'color': 'white'}
},
# "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": {
'ecart_20': {'color': 'red'},
'ecart_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 ####################
# TODO: Its not dry code!
# Buy Hyperoptable Parameters/Spaces.
# "buy_real_num0": 0.46,
# "buy_real_num1": 0.48,
# "buy_real_num2": 0.67
#
# buy_real_num0 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.46, space='buy')
# buy_real_num1 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.48, space='buy')
# buy_real_num2 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.67, space='buy')
profit_no_change = False
profit_old_sma10 = False
profit_over_rsi = True
profit_quick_gain = True
profit_quick_gain_3 = True
profit_quick_lost = False
profit_short_loss = False
profit_sma10 = False
profit_sma20 = True
profit_very_old_sma10 = False
# 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_decalage0 = IntParameter(1, 10, default=5, space='buy')
buy_real_num2 = DecimalParameter(1, 3, decimals=2, default=0.67, space='buy')
buy_decalage2 = IntParameter(1, 10, default=5, 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')
@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
}
]
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 >= -0.01) & ((current_time - trade.open_date_utc).days >= 5)\
& ((current_time - trade.open_date_utc).days < 10)\
& (previous_last_candle['sma20'] > last_candle['sma20']):
return "too_old_0.01"
if (current_profit >= -0.02) & ((current_time - trade.open_date_utc).days >= 10)\
& ((current_time - trade.open_date_utc).days < 15) \
& (previous_last_candle['sma20'] > last_candle['sma20']):
return "too_old_0.02"
if (current_profit >= -0.03) & ((current_time - trade.open_date_utc).days >= 15) \
& (previous_last_candle['sma20'] > last_candle['sma20']):
return "too_old_0.03"
if self.profit_quick_lost:
if (current_profit >= 0) & (last_candle['percent3'] < -0.015):
return "quick_lost"
if self.profit_no_change:
if (current_profit > 0.005) & (last_candle['percent10'] < 0.001) & (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 self.profit_sma10:
if (current_profit > 0.01) \
& ((previous_5_candle['sma10'] > last_candle['sma10'] * 1.005) \
| (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) & (last_candle['percent5'] < 0) \
& ((current_time - trade.open_date_utc).seconds >= 3600) \
& ((previous_last_candle['sma20'] > last_candle['sma20']) &
((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) & (last_candle['rsi'] > 88): # & (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'] > 82) & (last_candle['percent'] < -0.02): #| (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):
return []
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# dataframe['profit'] = 0
# RSI
dataframe['rsi'] = ta.RSI(dataframe)
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=72)
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["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_min'] = ta.MIN(dataframe['bb_lowerband'], timeperiod=36)
dataframe['distance_min'] = (dataframe['close'] - dataframe['min']) / dataframe['close']
dataframe['min1.1'] = 1.01 * dataframe['min']
# 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)
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
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)
conditions2 = list()
condition2, dataframe = condition_generator(
dataframe,
buy_operator0,
buy_indicator0,
buy_crossed_indicator0,
self.buy_real_num2.value,
self.buy_decalage2.value
)
conditions2.append(condition2)
if conditions:
for decalage in range(3, self.buy_decalage0.value):
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['min50'].shift(decalage) == dataframe['min50'])
& (dataframe['min10'] <= dataframe['min50'] * 1.02)
& (dataframe['percent20'].shift(decalage) <= -0.01)
# & (dataframe['min20'] == dataframe['min50'])
& (dataframe['distance_min'] <= 0.02)
), ['buy', 'buy_tag']] = (1, 'buy_1_' + str(decalage))
dataframe.loc[
(
(dataframe['cond1'].shift(decalage) <= 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['sma10'])
& (dataframe['min50'].shift(decalage) == dataframe['min50'])
#& (dataframe['min10'] <= dataframe['min50'] * 1.02)
& (dataframe['percent20'].shift(decalage) <= -0.02)
# & (dataframe['min20'] == dataframe['min50'])
& (dataframe['distance_min'] <= 0.02)
), ['buy', 'buy_tag']] = (1, 'buy_2_' + str(decalage))
# dataframe.loc[
# (
# (dataframe['cond1'].shift(decalage) <= 1.2)
# & (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= 10)
# # & (dataframe['sma10'].shift(1) <= dataframe['sma10'])
# & (dataframe['close'] < dataframe['sma10'])
# & (dataframe['open'] < dataframe['sma10'])
# & (dataframe['min50'].shift(decalage) == dataframe['min50'])
# #& (dataframe['min10'] <= dataframe['min50'] * 1.02)
# & (dataframe['percent20'].shift(decalage) <= -0.065)
# & (dataframe['distance_min'] <= 0.01)
# ), ['buy', 'buy_tag']] = (1, 'buy_3_' + str(decalage))
# if conditions2:
# for decalage in range(1, self.buy_decalage2.value): #self.buy_decalage.value):
# dataframe.loc[
# (
# reduce(lambda x, y: x & y, conditions2)
# & (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['min50'].shift(decalage) == dataframe['min50'])
# & (dataframe['bb_width'].shift(decalage) > self.buy_signal_bb_width.value)
# & (dataframe['percent20'].shift(decalage) <= -0.01)
# # & (dataframe['min20'] == dataframe['min50'])
# ), ['buy', 'buy_tag']] = (1, 'buy_3_' + str(decalage))
pandas.set_option('display.max_rows', dataframe.shape[0] + 1)
pandas.set_option('display.max_columns', 30)
# print(condition1)
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
return dataframe

45
GodStraJD3_7_4.json Normal file
View File

@@ -0,0 +1,45 @@
{
"strategy_name": "GodStraJD3_7_4",
"params": {
"roi": {
"0": 10
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.026,
"trailing_stop_positive_offset": 0.077,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_0": true,
"buy_0_distance": 0.04,
"buy_0_percent20": 0.02,
"buy_2": true,
"buy_2_distance": 0.02,
"buy_2_percent20": 0.08,
"buy_3": true,
"buy_3_distance": -0.06,
"buy_3_percent20": 0.1,
"buy_decalage0": 8,
"buy_decalage2": 8,
"buy_decalage3": 6,
"buy_decalage_deb_0": 3,
"buy_decalage_deb_2": 1,
"buy_decalage_deb_3": 3,
"buy_min_horizon": 83
},
"sell": {},
"protection": {
"lookback": 133,
"protection_max_allowed_dd": 0.71,
"protection_stop": 61,
"protection_stoploss_stop": 50,
"trade_limit": 9
}
},
"ft_stratparam_v": 1,
"export_time": "2022-03-08 17:38:42.327292+00:00"
}

804
GodStraJD3_7_4.py Normal file
View File

@@ -0,0 +1,804 @@
# 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 calendar
# --------------------------------
# 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
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'
# "buy_real_num0": 0.46,
# "buy_real_num1": 0.48,
# "buy_real_num2": 0.67
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_4(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'},
'sma10': {'color': 'yellow'},
'min20': {'color': '#87e470'},
'min50': {'color': '#ac3e2a'},
"min1.1": {'color': 'yellow'},
'sma20': {'color': 'cyan'}
},
'subplots': {
# Subplots - each dict defines one additional plot
"BB": {
'bb_width': {'color': 'white'}
},
# "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": {
'ecart_20': {'color': 'red'},
'ecart_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 ####################
# TODO: Its not dry code!
# Buy Hyperoptable Parameters/Spaces.
# "buy_real_num0": 0.46,
# "buy_real_num1": 0.48,
# "buy_real_num2": 0.67
#
# buy_real_num0 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.46, space='buy')
# buy_real_num1 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.48, space='buy')
# buy_real_num2 = DecimalParameter(0, 1, decimals=DECIMALS, default=0.67, space='buy')
profit_no_change = False
profit_old_sma10 = False
profit_over_rsi = True
profit_quick_gain = True
profit_quick_gain_3 = True
profit_quick_lost = False
profit_short_loss = False
profit_sma10 = False
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_decalage0 = IntParameter(1, 10, default=5, space='buy')
# #
# buy_real_num1 = DecimalParameter(0, 1, decimals=2, default=0.67, space='buy')
# buy_decalage1 = IntParameter(1, 10, default=5, space='buy')
#
# buy_real_num2 = DecimalParameter(1, 3, decimals=2, default=0.67, space='buy')
# buy_decalage2 = IntParameter(1, 10, default=5, 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(1, 3, default=5, space='buy')
buy_decalage_deb_2 = IntParameter(1, 3, default=5, space='buy')
buy_decalage_deb_3 = IntParameter(1, 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')
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')
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
}
]
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 >= -0.01) & ((current_time - trade.open_date_utc).days >= 5)\
& ((current_time - trade.open_date_utc).days < 10)\
& (previous_last_candle['sma20'] > last_candle['sma20']):
return "too_old_0.01"
if (current_profit >= -0.02) & ((current_time - trade.open_date_utc).days >= 10)\
& ((current_time - trade.open_date_utc).days < 15) \
& (previous_last_candle['sma20'] > last_candle['sma20']):
return "too_old_0.02"
if (current_profit >= -0.03) & ((current_time - trade.open_date_utc).days >= 15) \
& (previous_last_candle['sma20'] > last_candle['sma20']):
return "too_old_0.03"
if self.profit_quick_lost:
if (current_profit >= 0) & (last_candle['percent3'] < -0.015):
return "quick_lost"
if self.profit_no_change:
if (current_profit > 0.005) & (last_candle['percent10'] < 0.001) & (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 self.profit_sma10:
if (current_profit > 0.01) \
& ((previous_5_candle['sma10'] > last_candle['sma10'] * 1.005) \
| (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) & (last_candle['percent5'] < 0) \
& ((current_time - trade.open_date_utc).seconds >= 3600) \
& ((previous_last_candle['sma20'] > last_candle['sma20']) &
((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) & (last_candle['rsi'] > 88): # & (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'] > 82) & (last_candle['percent'] < -0.02): #| (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):
return []
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# dataframe['profit'] = 0
# RSI
dataframe['rsi'] = ta.RSI(dataframe)
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["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_min'] = ta.MIN(dataframe['bb_lowerband'], timeperiod=36)
dataframe['distance_min'] = (dataframe['close'] - dataframe['min']) / dataframe['close']
dataframe['min1.1'] = 1.01 * dataframe['min']
# 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)
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))
conditions = list()
condition1, dataframe = condition_generator(
dataframe,
buy_operator0,
buy_indicator0,
buy_crossed_indicator0,
0.9, #self.buy_real_num0.value,
6 #self.buy_decalage0.value
)
conditions.append(condition1)
conditions2 = list()
condition2, dataframe = condition_generator(
dataframe,
buy_operator0,
buy_indicator0,
buy_crossed_indicator0,
1.5, #self.buy_real_num2.value,
5 #self.buy_decalage2.value
)
conditions2.append(condition2)
if conditions:
for decalage in range(self.buy_decalage_deb_0.value, self.buy_decalage0.value):
if self.buy_0.value:
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['sma100'])
& (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)
), ['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['sma100'])
& (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)
), ['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['sma100'])
& (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)
), ['buy', 'buy_tag']] = (1, 'buy_3_' + str(decalage))
# if conditions2:
# for decalage in range(1, self.buy_decalage2.value): #self.buy_decalage.value):
# dataframe.loc[
# (
# reduce(lambda x, y: x & y, conditions2)
# & (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['min50'].shift(decalage) == dataframe['min50'])
# & (dataframe['bb_width'].shift(decalage) > self.buy_signal_bb_width.value)
# & (dataframe['percent20'].shift(decalage) <= -0.01)
# # & (dataframe['min20'] == dataframe['min50'])
# ), ['buy', 'buy_tag']] = (1, 'buy_4_' + str(decalage))
# 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

48
GodStraJD3_7_5.json Normal file
View File

@@ -0,0 +1,48 @@
{
"strategy_name": "GodStraJD3_7_5",
"params": {
"roi": {
"0": 10
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.026,
"trailing_stop_positive_offset": 0.077,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_0": true,
"buy_0_distance": 0.06,
"buy_0_percent20": 0.02,
"buy_2": true,
"buy_2_distance": 0.09,
"buy_2_percent20": 0.05,
"buy_3": true,
"buy_3_distance": 0.03,
"buy_3_percent20": 0.06,
"buy_decalage0": 7,
"buy_decalage2": 8,
"buy_decalage3": 6,
"buy_decalage_deb_0": 2,
"buy_decalage_deb_2": 1,
"buy_decalage_deb_3": 3,
"buy_min_horizon": 179,
"buy_real_num0": 0.82,
"buy_real_num1": 0.42,
"buy_real_num2": 0.21
},
"sell": {},
"protection": {
"lookback": 133,
"protection_max_allowed_dd": 0.71,
"protection_stop": 61,
"protection_stoploss_stop": 50,
"trade_limit": 9
}
},
"ft_stratparam_v": 1,
"export_time": "2022-03-09 00:06:48.822740+00:00"
}

764
GodStraJD3_7_5.py Normal file
View File

@@ -0,0 +1,764 @@
# 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 calendar
from freqtrade.loggers import setup_logging
# --------------------------------
# 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
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(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'},
'sma10': {'color': 'yellow'},
'min20': {'color': '#87e470'},
'min50': {'color': '#ac3e2a'},
"min1.1": {'color': 'yellow'},
'sma20': {'color': 'cyan'}
},
'subplots': {
# Subplots - each dict defines one additional plot
"BB": {
'bb_width': {'color': 'white'}
},
# "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 = False
profit_old_sma10 = False
profit_over_rsi = True
profit_quick_gain = True
profit_quick_gain_3 = True
profit_quick_lost = False
profit_short_loss = False
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_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(1, 3, default=5, space='buy')
buy_decalage_deb_2 = IntParameter(1, 3, default=5, space='buy')
buy_decalage_deb_3 = IntParameter(1, 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')
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')
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
}
]
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 >= -0.01) & ((current_time - trade.open_date_utc).days >= 5)\
& ((current_time - trade.open_date_utc).days < 10)\
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
return "too_old_0.01"
if (current_profit >= -0.02) & ((current_time - trade.open_date_utc).days >= 10)\
& ((current_time - trade.open_date_utc).days < 15) \
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
return "too_old_0.02"
if (current_profit >= -0.03) & ((current_time - trade.open_date_utc).days >= 15) \
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
return "too_old_0.03"
if self.profit_quick_lost:
if (current_profit >= 0) & (last_candle['percent3'] < -0.015):
return "quick_lost"
if self.profit_no_change:
if (current_profit > 0.005) & (last_candle['percent10'] < 0.001) & (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 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'] > 88): # & (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'] > 82) & (last_candle['percent'] < -0.02): #| (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):
return []
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# dataframe['profit'] = 0
# RSI
dataframe['rsi'] = ta.RSI(dataframe)
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_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()
# 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)
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))
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['sma100'])
& (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)
), ['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['sma100'])
& (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)
), ['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['sma100'])
& (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)
), ['buy', 'buy_tag']] = (1, 'buy_3_' + str(decalage))
# 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

57
GodStraJD3_7_5_1.json Normal file
View File

@@ -0,0 +1,57 @@
{
"strategy_name": "GodStraJD3_7_5_1",
"params": {
"roi": {
"0": 10
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.026,
"trailing_stop_positive_offset": 0.077,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_0": false,
"buy_0_percent20": 0.07,
"buy_1_decalage": 8,
"buy_1_decalage_deb": 2,
"buy_1_distance": 0.03,
"buy_1_min": 1.09,
"buy_1_normal_var": 4.1,
"buy_1_real_num": 0.13,
"buy_1_volume": 94,
"buy_2": false,
"buy_2_decalage": 8,
"buy_2_decalage_deb": 1,
"buy_2_distance": 0.06,
"buy_2_min": 1.07,
"buy_2_normal_var": 2.1,
"buy_2_percent20": -0.08,
"buy_2_real_num": 0.96,
"buy_2_volume": 19,
"buy_3": true,
"buy_3_decalage": 8,
"buy_3_decalage_deb": 2,
"buy_3_distance": 0.06,
"buy_3_min": 1.01,
"buy_3_normal_var": 0.8,
"buy_3_percent20": 0.01,
"buy_3_real_num": 0.19,
"buy_3_volume": 32,
"buy_min_horizon": 139
},
"sell": {},
"protection": {
"lookback": 133,
"protection_max_allowed_dd": 0.71,
"protection_stop": 61,
"protection_stoploss_stop": 50,
"trade_limit": 9
}
},
"ft_stratparam_v": 1,
"export_time": "2022-03-17 11:40:13.234887+00:00"
}

823
GodStraJD3_7_5_1.py Normal file
View File

@@ -0,0 +1,823 @@
# 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 calendar
from freqtrade.loggers import setup_logging
# --------------------------------
# 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
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_1(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'},
'sma10': {'color': 'yellow'},
'min20': {'color': '#87e470'},
'min50': {'color': '#ac3e2a'},
"min1.1": {'color': 'yellow'},
'sma20': {'color': 'cyan'}
},
'subplots': {
# Subplots - each dict defines one additional plot
"BB": {
'bb_width': {'color': 'white'}
},
# "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 = False
profit_old_sma10 = False
profit_over_rsi = True
profit_quick_gain = True
profit_quick_gain_3 = True
profit_quick_lost = False
profit_short_loss = False
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_1_real_num = DecimalParameter(0, 1, decimals=2, default=0.67, space='buy')
buy_2_real_num = DecimalParameter(0, 1, decimals=2, default=0.67, space='buy')
buy_3_real_num = DecimalParameter(0, 2, 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_1_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_1_min = DecimalParameter(1, 1.1, decimals=2, default=1.02, space='buy')
buy_2_min = DecimalParameter(1, 1.1, decimals=2, default=1.02, space='buy')
buy_3_min = DecimalParameter(1, 1.1, decimals=2, default=1.02, space='buy')
buy_1_normal_var = DecimalParameter(0, 5, decimals=1, default=0, space='buy')
buy_2_normal_var = DecimalParameter(0, 5, decimals=1, default=0, space='buy')
buy_3_normal_var = DecimalParameter(0, 5, decimals=1, default=0, space='buy')
buy_1_decalage_deb = IntParameter(1, 3, default=5, space='buy')
buy_2_decalage_deb = IntParameter(1, 3, default=5, space='buy')
buy_3_decalage_deb = IntParameter(1, 3, default=5, space='buy')
buy_1_decalage = IntParameter(buy_1_decalage_deb.value + 1, 8, default=5, space='buy')
buy_2_decalage = IntParameter(buy_2_decalage_deb.value + 1, 8, default=5, space='buy')
buy_3_decalage = IntParameter(buy_3_decalage_deb.value + 1, 8, default=5, space='buy')
buy_1_volume = IntParameter(0, 100, default=10, space='buy')
buy_2_volume = IntParameter(0, 100, default=10, space='buy')
buy_3_volume = IntParameter(0, 100, default=10, 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')
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
proposed_stake: float, min_stake: float, max_stake: float,
**kwargs) -> float:
dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
current_candle = dataframe.iloc[-1].squeeze()
# for decalage in range(self.buy_3_decalage_deb.value, self.buy_3_decalage.value):
# decalage_candle = dataframe.iloc[- decalage].squeeze()
# # if (decalage_candle['normal_var_20'] >= 0.6):
# amount = 10 * (- decalage_candle['percent20'] * 100)
# print("use more stake", pair, " ", amount)
# return min(max_stake, amount)
# print("proposed_stake=", proposed_stake, " max_stake=", max_stake)
# if current_candle['bb_width'] > 0.05:
# print("use more stake", pair, " ", proposed_stake * 2)
# return min(max_stake, proposed_stake * 2)
#
# if current_candle['bb_width'] > 0.035:
# print("use more stake", pair, " ", proposed_stake * 1.5)
# return min(max_stake, proposed_stake * 1.5)
# if current_candle['bb_width'] < 0.020:
# print("use less stake", pair, " ", proposed_stake / 2)
# return min(max_stake, proposed_stake / 2)
# if self.config['stake_amount'] == 'unlimited':
# # Use entire available wallet during favorable conditions when in compounding mode.
# return max_stake
# else:
# # Compound profits during favorable conditions instead of using a static stake.
# return self.wallets.get_total_stake_amount() / self.config['max_open_trades']
# Use default stake amount.
return proposed_stake
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
}
]
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 >= -0.01) & ((current_time - trade.open_date_utc).days >= 5)\
& ((current_time - trade.open_date_utc).days < 10)\
& (previous_last_candle['sma20'] > last_candle['sma20']):
return "too_old_0.01"
if (current_profit >= -0.02) & ((current_time - trade.open_date_utc).days >= 10)\
& ((current_time - trade.open_date_utc).days < 15) \
& (previous_last_candle['sma20'] > last_candle['sma20']):
return "too_old_0.02"
if (current_profit >= -0.03) & ((current_time - trade.open_date_utc).days >= 15) \
& (previous_last_candle['sma20'] > last_candle['sma20']):
return "too_old_0.03"
if self.profit_quick_lost:
if (current_profit >= 0) & (last_candle['percent3'] < -0.015):
return "quick_lost"
if self.profit_no_change:
if (current_profit > 0.005) & (last_candle['percent10'] < 0.001) & (last_candle['percent5'] < 0) & ((current_time - trade.open_date_utc).seconds >= 3600):
return "no_change"
if (current_profit > 0.005) & (last_candle['normal_var_20'] < 0.008):
return "no_change_20"
if (current_profit > 0.01) & (last_candle['normal_var_10'] < 0.008):
return "no_change_10"
if (current_profit > 0.01) & (last_candle['normal_var_5'] < 0.005):
return "no_change_5"
#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 self.profit_sma10:
if (current_profit > 0.01) \
& ((previous_5_candle['sma10'] > last_candle['sma10'] * 1.005) \
| (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) & (last_candle['rsi'] > 88): # & (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'] > 82) & (last_candle['percent'] < -0.02): #| (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):
return []
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# dataframe['profit'] = 0
# RSI
dataframe['rsi'] = ta.RSI(dataframe)
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_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_5'] = dataframe['normal'].rolling(5).var()
dataframe['normal_var_10'] = dataframe['normal'].rolling(10).var()
dataframe['normal_var_20'] = dataframe['normal'].rolling(20).var()
dataframe['normal_var_50'] = dataframe['normal'].rolling(50).var()
# 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)
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))
for decalage in range(self.buy_1_decalage_deb.value, self.buy_1_decalage.value):
if self.buy_0.value:
conditions = list()
condition1, dataframe = condition_generator(
dataframe,
buy_operator0,
buy_indicator0,
buy_crossed_indicator0,
self.buy_1_real_num.value,
self.buy_1_decalage.value
)
conditions.append(condition1)
dataframe.loc[
(
reduce(lambda x, y: x & y, conditions)
& (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= self.buy_1_volume.value)
& (dataframe['sma10'].shift(1) <= dataframe['sma10'])
& (dataframe['close'] < dataframe['bb_middleband'])
& (dataframe['open'] < dataframe['sma10'])
& (dataframe['open'] < dataframe['sma100'])
& (dataframe['min50'].shift(decalage) == dataframe['min50'])
& (dataframe['min10'] <= dataframe['min50'] * self.buy_1_min.value)
& (dataframe['percent20'].shift(decalage) <= self.buy_0_percent20.value)
# & (dataframe['min20'] == dataframe['min50'])
& (dataframe['distance_min'] <= self.buy_1_distance.value)
& (dataframe['normal_var_20'] >= self.buy_1_normal_var.value)
), ['buy', 'buy_tag']] = (1, 'buy_1_' + str(decalage))
for decalage in range(self.buy_2_decalage_deb.value, self.buy_2_decalage.value):
if self.buy_2.value:
dataframe.loc[
(
(dataframe['cond1'].shift(decalage) <= 0.45) #self.buy_1_real_num.value / 2)
& (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= self.buy_2_volume.value)
# & (dataframe['sma10'].shift(1) <= dataframe['sma10'])
& (dataframe['close'] < dataframe['sma10'])
& (dataframe['open'] < dataframe['sma100'])
& (dataframe['open'] < dataframe['sma10'])
& (dataframe['min50'].shift(decalage) == dataframe['min50'])
# & (dataframe['min10'] <= dataframe['min50'] * self.buy_2_min.value)
& (dataframe['percent20'].shift(decalage) <= self.buy_2_percent20.value)
# & (dataframe['min20'] == dataframe['min50'])
& (dataframe['distance_min'] <= self.buy_2_distance.value)
& (dataframe['normal_var_20'] >= self.buy_2_normal_var.value)
), ['buy', 'buy_tag']] = (1, 'buy_2_' + str(decalage))
for decalage in range(self.buy_3_decalage_deb.value, self.buy_3_decalage.value):
if self.buy_3.value:
dataframe.loc[
(
(dataframe['cond1'].shift(decalage) <= 0.2)
& (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= self.buy_3_volume.value)
# & (dataframe['sma10'].shift(1) <= dataframe['sma10'])
& (dataframe['close'] < dataframe['sma10'])
& (dataframe['open'] < dataframe['sma100'])
& (dataframe['open'] < dataframe['sma10'])
& (dataframe['min50'].shift(decalage) == dataframe['min50'])
# & (dataframe['min10'] <= dataframe['min50'] * self.buy_3_min.value)
& (dataframe['percent20'].shift(decalage) <= self.buy_3_percent20.value)
& (dataframe['distance_min'] <= self.buy_3_distance.value)
& (dataframe['normal_var_20'] >= self.buy_3_normal_var.value)
), ['buy', 'buy_tag']] = (1, 'buy_3_' + str(decalage))
# 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

72
GodStraJD3_7_5_10.json Normal file
View File

@@ -0,0 +1,72 @@
{
"strategy_name": "GodStraJD3_7_5_10",
"params": {
"roi": {
"0": 10
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.026,
"trailing_stop_positive_offset": 0.077,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_0_distance": 0.01,
"buy_0_percent20": 0.1,
"buy_1_bb_lower_5": 0.52,
"buy_1_pente_sma10": 0.25,
"buy_1_pente_sma20": 0.38,
"buy_1_percent_5m_num": -0.04,
"buy_2_bb_lower_5": 0.56,
"buy_2_distance": 0.1,
"buy_2_pente_sma10": 0.55,
"buy_2_pente_sma20": 0.25,
"buy_2_percent20": 0.04,
"buy_2_percent_5m_num": -0.07,
"buy_3_bb_lower_5": 0.6,
"buy_3_distance": -0.01,
"buy_3_pente_sma10": 0.32,
"buy_3_pente_sma20": 0.5,
"buy_3_percent20": 0.09,
"buy_3_percent_5m_num": -0.04,
"buy_4_day_week_percent": 0.0,
"buy_4_pente_sma10": 0.56,
"buy_4_pente_sma20": 0.13,
"buy_day_week": "percent3_1d",
"buy_decalage0": 7,
"buy_decalage2": 8,
"buy_decalage3": 8,
"buy_decalage_deb_0": 3,
"buy_decalage_deb_2": 0,
"buy_decalage_deb_3": 0,
"buy_min_horizon": 83,
"buy_real_num0": 1.63,
"buy_real_num1": 0.42,
"buy_real_num2": 0.38
},
"sell": {
"sell_RSI": 89,
"sell_RSI2": 78,
"sell_RSI2_percent": 0.001,
"sell_candels": 4,
"sell_percent": 0.02,
"sell_percent3": 0.014,
"sell_profit_no_change": 0.02,
"sell_profit_percent10": 0.0013,
"sell_too_old_day": 7,
"sell_too_old_percent": 0.019
},
"protection": {
"lookback": 133,
"protection_max_allowed_dd": 0.71,
"protection_stop": 61,
"protection_stoploss_stop": 50,
"trade_limit": 9
}
},
"ft_stratparam_v": 1,
"export_time": "2022-03-29 07:11:59.278799+00:00"
}

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

51
GodStraJD3_7_5_2.json Normal file
View File

@@ -0,0 +1,51 @@
{
"strategy_name": "GodStraJD3_7_5_2",
"params": {
"roi": {
"0": 2
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.02,
"trailing_stop_positive_offset": 0.03,
"trailing_only_offset_is_reached": false
},
"buy": {
"buy_1": false,
"buy_1_bb_diff_lower": 0.0007,
"buy_1_decalage": 6,
"buy_1_decalage_deb": 1,
"buy_1_distance": 0.03,
"buy_1_percent20": 0.06,
"buy_1_real_num": 0.1,
"buy_2": false,
"buy_2_bb_diff_lower": 0.0004,
"buy_2_decalage": 7,
"buy_2_decalage_deb": 3,
"buy_2_distance": 0.06,
"buy_2_percent20": 0.01,
"buy_2_real_num": 1.7,
"buy_3": true,
"buy_3_bb_diff_lower": 0.0,
"buy_3_decalage": 7,
"buy_3_decalage_deb": 2,
"buy_3_distance": 0.09,
"buy_3_percent20": 0.01,
"buy_3_real_num": 0.99,
"buy_min_horizon": 191
},
"sell": {},
"protection": {
"lookback": 133,
"protection_max_allowed_dd": 0.71,
"protection_stop": 61,
"protection_stoploss_stop": 50,
"trade_limit": 9
}
},
"ft_stratparam_v": 1,
"export_time": "2022-03-12 21:14:24.255458+00:00"
}

781
GodStraJD3_7_5_2.py Normal file
View File

@@ -0,0 +1,781 @@
# 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 calendar
from freqtrade.loggers import setup_logging
# --------------------------------
# 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
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_2(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'},
'sma10': {'color': 'yellow'},
'min20': {'color': '#87e470'},
'min50': {'color': '#ac3e2a'},
"min1.1": {'color': 'yellow'},
'sma20': {'color': 'cyan'}
},
'subplots': {
# Subplots - each dict defines one additional plot
"BB": {
'bb_width': {'color': 'white'}
},
# "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'},
"bb_diff_lower": {'color': 'white'}
}
}
}
# #################### END OF RESULT PLACE ####################
profit_no_change = False
profit_old_sma10 = False
profit_over_rsi = True
profit_quick_gain = True
profit_quick_gain_3 = True
profit_quick_lost = False
profit_short_loss = False
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_1_real_num = DecimalParameter(0, 1, decimals=2, default=0.67, space='buy')
buy_2_real_num = DecimalParameter(0, 2, decimals=2, default=0.67, space='buy')
buy_3_real_num = DecimalParameter(0, 1, decimals=2, default=0.67, space='buy')
buy_min_horizon = IntParameter(50, 200, default=72, space='buy')
buy_1 = BooleanParameter(default=True, space="buy")
buy_2 = BooleanParameter(default=True, space="buy")
buy_3 = BooleanParameter(default=True, space="buy")
buy_1_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_1_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_1_bb_diff_lower = DecimalParameter(0, 0.001, decimals=4, default=0.0009, space='buy')
buy_2_bb_diff_lower = DecimalParameter(0, 0.001, decimals=4, default=0.0009, space='buy')
buy_3_bb_diff_lower = DecimalParameter(0, 0.001, decimals=4, default=0.0009, space='buy')
buy_1_decalage_deb = IntParameter(1, 3, default=5, space='buy')
buy_2_decalage_deb = IntParameter(1, 3, default=5, space='buy')
buy_3_decalage_deb = IntParameter(1, 3, default=5, space='buy')
buy_1_decalage = IntParameter(buy_1_decalage_deb.value + 1, 8, default=5, space='buy')
buy_2_decalage = IntParameter(buy_2_decalage_deb.value + 1, 8, default=5, space='buy')
buy_3_decalage = IntParameter(buy_3_decalage_deb.value + 1, 8, default=5, 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')
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
}
]
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'
days = (current_time - trade.open_date_utc).days
# if (current_profit >= -0.01 * days) & (days >= 5) \
# & (previous_last_candle['sma20'] > last_candle['sma20']):
# return "too_old_" + days
if (current_profit >= -0.01) & (days >= 5) & (days < 10)\
& (previous_last_candle['sma20'] > last_candle['sma20']):
return "too_old_0.01"
if (current_profit >= -0.02) & (days >= 10) & (days < 15) \
& (previous_last_candle['sma20'] > last_candle['sma20']):
return "too_old_0.02"
if (current_profit >= -0.03) & (days >= 15) \
& (previous_last_candle['sma20'] > last_candle['sma20']):
return "too_old_0.03"
if self.profit_quick_lost:
if (current_profit >= 0) & (last_candle['percent3'] < -0.015):
return "quick_lost"
if self.profit_no_change:
if (current_profit > 0.005) & (last_candle['percent10'] < 0.001) & (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 self.profit_sma10:
if (current_profit > 0.01) \
& ((previous_5_candle['sma10'] > last_candle['sma10'] * 1.005) \
| (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) \
# & (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) \
# & (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'] > 88) \
# & (
# (last_candle['percent'] < - current_profit / 3) | (last_candle['percent3'] < - current_profit / 3)):
# # print("over_rsi", pair, trade, " profit=", current_profit, " rate=", current_rate)
# return 'over_rsi'
if (current_profit > 0) & (last_candle['rsi'] > 88): # & (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'] > 82) & (last_candle['percent'] < -0.02): #| (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)\
& (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):
return []
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# dataframe['profit'] = 0
# RSI
dataframe['rsi'] = ta.RSI(dataframe)
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['volume_max'] = dataframe['volume10'] * dataframe['close'] / 1000
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_diff_lower"] = (dataframe["bb_lowerband"] - dataframe["bb_lowerband"].shift(1)) / dataframe["bb_lowerband"]
# 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()) - 100
dataframe['normal_var_20'] = dataframe['normal'].rolling(20).var()
dataframe['normal_var_50'] = dataframe['normal'].rolling(50).var()
# 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)
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))
for decalage in range(self.buy_1_decalage_deb.value, self.buy_1_decalage.value):
if self.buy_1.value:
conditions = list()
condition1, dataframe = condition_generator(
dataframe,
buy_operator0,
buy_indicator0,
buy_crossed_indicator0,
self.buy_1_real_num.value,
self.buy_1_decalage.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['sma100'])
& (dataframe['min50'].shift(decalage) == dataframe['min50'])
& (dataframe['min10'] <= dataframe['min50'] * 1.02)
& (dataframe['percent20'].shift(decalage) <= self.buy_1_percent20.value)
# & (dataframe['min20'] == dataframe['min50'])
& (dataframe['bb_diff_lower'] >= - self.buy_1_bb_diff_lower.value)
# & (dataframe['distance_min'] <= self.buy_1_distance.value)
), ['buy', 'buy_tag']] = (1, 'buy_1_' + str(decalage))
for decalage in range(self.buy_2_decalage_deb.value, self.buy_2_decalage.value):
if self.buy_2.value:
dataframe.loc[
(
(dataframe['cond1'].shift(decalage) <= self.buy_2_real_num.value)
& (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= 10)
# & (dataframe['sma10'].shift(1) <= dataframe['sma10'])
& (dataframe['close'] < dataframe['sma10'])
& (dataframe['open'] < dataframe['sma100'])
& (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)
), ['buy', 'buy_tag']] = (1, 'buy_2_' + str(decalage))
for decalage in range(self.buy_3_decalage_deb.value, self.buy_3_decalage.value):
if self.buy_3.value:
dataframe.loc[
(
(dataframe['cond1'].shift(decalage) <= self.buy_3_real_num.value)
& (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= 10)
# & (dataframe['sma10'].shift(1) <= dataframe['sma10'])
# & (dataframe['bb_width'] >= 0.07)
& (dataframe['close'] < dataframe['sma10'])
& (dataframe['open'] < dataframe['sma100'])
& (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['bb_diff_lower'] >= - self.buy_3_bb_diff_lower.value)
), ['buy', 'buy_tag']] = (1, 'buy_3_' + str(decalage))
# 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

51
GodStraJD3_7_5_3.json Normal file
View File

@@ -0,0 +1,51 @@
{
"strategy_name": "GodStraJD3_7_5_3",
"params": {
"roi": {
"0": 10
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.026,
"trailing_stop_positive_offset": 0.077,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_0": false,
"buy_0_percent20": -0.07,
"buy_1_decalage": 6,
"buy_1_decalage_deb": 3,
"buy_1_distance": 0.02,
"buy_1_normal_var": 5.0,
"buy_1_real_num": 0.61,
"buy_2": true,
"buy_2_decalage": 6,
"buy_2_decalage_deb": 1,
"buy_2_distance": 0.1,
"buy_2_normal_var": 0.0,
"buy_2_percent20": 0.02,
"buy_2_real_num": 0.35,
"buy_3": true,
"buy_3_decalage": 6,
"buy_3_decalage_deb": 2,
"buy_3_distance": 0.01,
"buy_3_normal_var": 1.8,
"buy_3_percent20": -0.03,
"buy_3_real_num": 1.18,
"buy_min_horizon": 165
},
"sell": {},
"protection": {
"lookback": 133,
"protection_max_allowed_dd": 0.71,
"protection_stop": 61,
"protection_stoploss_stop": 50,
"trade_limit": 9
}
},
"ft_stratparam_v": 1,
"export_time": "2022-03-13 17:21:19.281512+00:00"
}

51
GodStraJD3_7_5_3.json1 Normal file
View File

@@ -0,0 +1,51 @@
{
"strategy_name": "GodStraJD3_7_5_3",
"params": {
"roi": {
"0": 10
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.026,
"trailing_stop_positive_offset": 0.077,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_0": true,
"buy_0_percent20": 0.09,
"buy_1_decalage": 6,
"buy_1_decalage_deb": 1,
"buy_1_distance": 0.06,
"buy_1_normal_var": 4.7,
"buy_1_real_num": 0.96,
"buy_2": true,
"buy_2_decalage": 6,
"buy_2_decalage_deb": 2,
"buy_2_distance": 0.03,
"buy_2_normal_var": 1.6,
"buy_2_percent20": 0.09,
"buy_2_real_num": 0.08,
"buy_3": false,
"buy_3_decalage": 6,
"buy_3_decalage_deb": 2,
"buy_3_distance": -0.08,
"buy_3_normal_var": 1.9,
"buy_3_percent20": -0.06,
"buy_3_real_num": 0.81,
"buy_min_horizon": 186
},
"sell": {},
"protection": {
"lookback": 133,
"protection_max_allowed_dd": 0.71,
"protection_stop": 61,
"protection_stoploss_stop": 50,
"trade_limit": 9
}
},
"ft_stratparam_v": 1,
"export_time": "2022-03-12 23:10:38.145463+00:00"
}

808
GodStraJD3_7_5_3.py Normal file
View File

@@ -0,0 +1,808 @@
# 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 calendar
from freqtrade.loggers import setup_logging
# --------------------------------
# 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
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_3(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'},
'sma10': {'color': 'yellow'},
'min20': {'color': '#87e470'},
'min50': {'color': '#ac3e2a'},
"min1.1": {'color': 'yellow'},
'sma20': {'color': 'cyan'}
},
'subplots': {
# Subplots - each dict defines one additional plot
"BB": {
'bb_width': {'color': 'white'}
},
# "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 = False
profit_old_sma10 = False
profit_over_rsi = True
profit_quick_gain = True
profit_quick_gain_3 = True
profit_quick_lost = False
profit_short_loss = False
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_1_real_num = DecimalParameter(0, 1, decimals=2, default=0.67, space='buy')
buy_2_real_num = DecimalParameter(0, 1, decimals=2, default=0.67, space='buy')
buy_3_real_num = DecimalParameter(0, 2, 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_1_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_1_normal_var = DecimalParameter(0, 5, decimals=1, default=0, space='buy')
buy_2_normal_var = DecimalParameter(0, 5, decimals=1, default=0, space='buy')
buy_3_normal_var = DecimalParameter(0, 5, decimals=1, default=0, space='buy')
buy_1_decalage_deb = IntParameter(1, 3, default=5, space='buy')
buy_2_decalage_deb = IntParameter(1, 3, default=5, space='buy')
buy_3_decalage_deb = IntParameter(1, 3, default=5, space='buy')
buy_1_decalage = IntParameter(buy_1_decalage_deb.value + 1, 8, default=5, space='buy')
buy_2_decalage = IntParameter(buy_2_decalage_deb.value + 1, 8, default=5, space='buy')
buy_3_decalage = IntParameter(buy_3_decalage_deb.value + 1, 8, default=5, 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')
# def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
# proposed_stake: float, min_stake: float, max_stake: float,
# **kwargs) -> float:
#
# dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
# current_candle = dataframe.iloc[-1].squeeze()
#
# # print("proposed_stake=", proposed_stake, " max_stake=", max_stake)
# # if current_candle['bb_width'] > 0.05:
# # print("use more stake", pair, " ", proposed_stake * 2)
# # return min(max_stake, proposed_stake * 2)
# #
# # if current_candle['bb_width'] > 0.035:
# # print("use more stake", pair, " ", proposed_stake * 1.5)
# # return min(max_stake, proposed_stake * 1.5)
#
# # if current_candle['bb_width'] < 0.020:
# # print("use less stake", pair, " ", proposed_stake / 2)
# # return min(max_stake, proposed_stake / 2)
# # if self.config['stake_amount'] == 'unlimited':
# # # Use entire available wallet during favorable conditions when in compounding mode.
# # return max_stake
# # else:
# # # Compound profits during favorable conditions instead of using a static stake.
# # return self.wallets.get_total_stake_amount() / self.config['max_open_trades']
#
#
# # Use default stake amount.
# return proposed_stake
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
}
]
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 >= -0.01) & ((current_time - trade.open_date_utc).days >= 5)\
& ((current_time - trade.open_date_utc).days < 10)\
& (previous_last_candle['sma20'] > last_candle['sma20']):
return "too_old_0.01"
if (current_profit >= -0.02) & ((current_time - trade.open_date_utc).days >= 10)\
& ((current_time - trade.open_date_utc).days < 15) \
& (previous_last_candle['sma20'] > last_candle['sma20']):
return "too_old_0.02"
if (current_profit >= -0.03) & ((current_time - trade.open_date_utc).days >= 15) \
& (previous_last_candle['sma20'] > last_candle['sma20']):
return "too_old_0.03"
if self.profit_quick_lost:
if (current_profit >= 0) & (last_candle['percent3'] < -0.015):
return "quick_lost"
if self.profit_no_change:
if (current_profit > 0.005) & (last_candle['percent10'] < 0.001) & (last_candle['percent5'] < 0) & ((current_time - trade.open_date_utc).seconds >= 3600):
return "no_change"
if (current_profit > 0.005) & (last_candle['normal_var_20'] < 0.008) & (last_candle['percent3'] < 0):
return "no_change_20"
if (current_profit > 0.01) & (last_candle['normal_var_10'] < 0.008) & (last_candle['percent3'] < 0):
return "no_change_10"
if (current_profit > 0.01) & (last_candle['normal_var_5'] < 0.005) & (last_candle['percent3'] < 0):
return "no_change_5"
#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 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) & (last_candle['rsi'] > 88): # & (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'] > 82) & (last_candle['percent'] < -0.02): #| (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):
return []
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# dataframe['profit'] = 0
# RSI
dataframe['rsi'] = ta.RSI(dataframe)
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_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_5'] = dataframe['normal'].rolling(5).var()
dataframe['normal_var_10'] = dataframe['normal'].rolling(10).var()
dataframe['normal_var_20'] = dataframe['normal'].rolling(20).var()
dataframe['normal_var_50'] = dataframe['normal'].rolling(50).var()
# 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)
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))
for decalage in range(self.buy_1_decalage_deb.value, self.buy_1_decalage.value):
if self.buy_0.value:
conditions = list()
condition1, dataframe = condition_generator(
dataframe,
buy_operator0,
buy_indicator0,
buy_crossed_indicator0,
self.buy_1_real_num.value,
self.buy_1_decalage.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['sma100'])
& (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_1_distance.value)
& (dataframe['normal_var_20'] >= self.buy_1_normal_var.value)
), ['buy', 'buy_tag']] = (1, 'buy_1_' + str(decalage))
for decalage in range(self.buy_2_decalage_deb.value, self.buy_2_decalage.value):
if self.buy_2.value:
dataframe.loc[
(
(dataframe['cond1'].shift(decalage) <= 0.45) #self.buy_1_real_num.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['sma100'])
& (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['normal_var_20'] >= self.buy_2_normal_var.value)
), ['buy', 'buy_tag']] = (1, 'buy_2_' + str(decalage))
for decalage in range(self.buy_3_decalage_deb.value, self.buy_3_decalage.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['sma100'])
& (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['normal_var_20'] >= self.buy_3_normal_var.value)
), ['buy', 'buy_tag']] = (1, 'buy_3_' + str(decalage))
# 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

57
GodStraJD3_7_5_4.json Normal file
View File

@@ -0,0 +1,57 @@
{
"strategy_name": "GodStraJD3_7_5_4",
"params": {
"roi": {
"0": 10
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.026,
"trailing_stop_positive_offset": 0.077,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_0": false,
"buy_0_percent20": 0.02,
"buy_1_decalage": 8,
"buy_1_decalage_deb": 3,
"buy_1_distance": 0.07,
"buy_1_min": 1.029,
"buy_1_normal_var": 3.5,
"buy_1_real_num": 0.47,
"buy_1_volume": 71,
"buy_2": true,
"buy_2_decalage": 8,
"buy_2_decalage_deb": 2,
"buy_2_distance": 0.06,
"buy_2_min": 1.029,
"buy_2_normal_var": 0.3,
"buy_2_percent20": 0.06,
"buy_2_real_num": 0.38,
"buy_2_volume": 13,
"buy_3": true,
"buy_3_decalage": 7,
"buy_3_decalage_deb": 2,
"buy_3_distance": 0.03,
"buy_3_min": 1.008,
"buy_3_normal_var": 3.2,
"buy_3_percent20": 0.09,
"buy_3_real_num": 0.73,
"buy_3_volume": 12,
"buy_min_horizon": 141
},
"sell": {},
"protection": {
"lookback": 133,
"protection_max_allowed_dd": 0.71,
"protection_stop": 61,
"protection_stoploss_stop": 50,
"trade_limit": 9
}
},
"ft_stratparam_v": 1,
"export_time": "2022-03-17 23:12:39.259525+00:00"
}

827
GodStraJD3_7_5_4.py Normal file
View File

@@ -0,0 +1,827 @@
# 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 calendar
from freqtrade.loggers import setup_logging
from technical.indicators import cmf
# --------------------------------
# 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
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_4(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'},
'sma10': {'color': 'yellow'},
'min20': {'color': '#87e470'},
'min50': {'color': '#ac3e2a'},
"min1.1": {'color': 'yellow'},
'sma20': {'color': 'cyan'}
},
'subplots': {
# Subplots - each dict defines one additional plot
"BB": {
'bb_width': {'color': 'white'}
},
# "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 = False
profit_old_sma10 = False
profit_over_rsi = True
profit_quick_gain = True
profit_quick_gain_3 = True
profit_quick_lost = False
profit_short_loss = False
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_1_real_num = DecimalParameter(0, 1, decimals=2, default=0.67, space='buy')
buy_2_real_num = DecimalParameter(0, 1, decimals=2, default=0.67, space='buy')
buy_3_real_num = DecimalParameter(0, 2, 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_1_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_1_min = DecimalParameter(1, 1.03, decimals=3, default=1.02, space='buy')
buy_2_min = DecimalParameter(1, 1.03, decimals=3, default=1.02, space='buy')
buy_3_min = DecimalParameter(1, 1.03, decimals=3, default=1.02, space='buy')
buy_1_normal_var = DecimalParameter(0, 5, decimals=1, default=0, space='buy')
buy_2_normal_var = DecimalParameter(0, 5, decimals=1, default=0, space='buy')
buy_3_normal_var = DecimalParameter(0, 5, decimals=1, default=0, space='buy')
buy_1_decalage_deb = IntParameter(1, 3, default=5, space='buy')
buy_2_decalage_deb = IntParameter(1, 3, default=5, space='buy')
buy_3_decalage_deb = IntParameter(1, 3, default=5, space='buy')
buy_1_decalage = IntParameter(buy_1_decalage_deb.value + 1, 8, default=5, space='buy')
buy_2_decalage = IntParameter(buy_2_decalage_deb.value + 1, 8, default=5, space='buy')
buy_3_decalage = IntParameter(buy_3_decalage_deb.value + 1, 8, default=5, space='buy')
buy_1_volume = IntParameter(0, 100, default=10, space='buy')
buy_2_volume = IntParameter(0, 100, default=10, space='buy')
buy_3_volume = IntParameter(0, 100, default=10, 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')
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
proposed_stake: float, min_stake: float, max_stake: float,
**kwargs) -> float:
dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
current_candle = dataframe.iloc[-1].squeeze()
# for decalage in range(self.buy_3_decalage_deb.value, self.buy_3_decalage.value):
# decalage_candle = dataframe.iloc[- decalage].squeeze()
# # if (decalage_candle['normal_var_20'] >= 0.6):
# amount = 10 * (- decalage_candle['percent20'] * 100)
# print("use more stake", pair, " ", amount)
# return min(max_stake, amount)
# print("proposed_stake=", proposed_stake, " max_stake=", max_stake)
# if current_candle['bb_width'] > 0.05:
# print("use more stake", pair, " ", proposed_stake * 2)
# return min(max_stake, proposed_stake * 2)
#
# if current_candle['bb_width'] > 0.035:
# print("use more stake", pair, " ", proposed_stake * 1.5)
# return min(max_stake, proposed_stake * 1.5)
# if current_candle['bb_width'] < 0.020:
# print("use less stake", pair, " ", proposed_stake / 2)
# return min(max_stake, proposed_stake / 2)
# if self.config['stake_amount'] == 'unlimited':
# # Use entire available wallet during favorable conditions when in compounding mode.
# return max_stake
# else:
# # Compound profits during favorable conditions instead of using a static stake.
# return self.wallets.get_total_stake_amount() / self.config['max_open_trades']
# Use default stake amount.
return proposed_stake
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
}
]
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 >= -0.01) & ((current_time - trade.open_date_utc).days >= 5)\
& ((current_time - trade.open_date_utc).days < 10)\
& (previous_last_candle['sma20'] > last_candle['sma20']):
return "too_old_0.01"
if (current_profit >= -0.02) & ((current_time - trade.open_date_utc).days >= 10)\
& ((current_time - trade.open_date_utc).days < 15) \
& (previous_last_candle['sma20'] > last_candle['sma20']):
return "too_old_0.02"
if (current_profit >= -0.03) & ((current_time - trade.open_date_utc).days >= 15) \
& (previous_last_candle['sma20'] > last_candle['sma20']):
return "too_old_0.03"
if self.profit_quick_lost:
if (current_profit >= 0) & (last_candle['percent3'] < -0.015):
return "quick_lost"
if self.profit_no_change:
if (current_profit > 0.005) & (last_candle['percent10'] < 0.001) & (last_candle['percent5'] < 0) & ((current_time - trade.open_date_utc).seconds >= 3600):
return "no_change"
if (current_profit > 0.005) & (last_candle['normal_var_20'] < 0.008):
return "no_change_20"
if (current_profit > 0.01) & (last_candle['normal_var_10'] < 0.008):
return "no_change_10"
if (current_profit > 0.01) & (last_candle['normal_var_5'] < 0.005):
return "no_change_5"
#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 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) & (last_candle['rsi'] > 88): # & (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'] > 82) & (last_candle['percent'] < -0.02): #| (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):
return []
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# dataframe['profit'] = 0
# RSI
dataframe['rsi'] = ta.RSI(dataframe)
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_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_5'] = dataframe['normal'].rolling(5).var()
dataframe['normal_var_10'] = dataframe['normal'].rolling(10).var()
dataframe['normal_var_20'] = dataframe['normal'].rolling(20).var()
dataframe['normal_var_50'] = dataframe['normal'].rolling(50).var()
# 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['cmf20'] = cmf(dataframe, 20)
dataframe['cmf50'] = cmf(dataframe, 50)
dataframe['cmf100'] = cmf(dataframe, 100)
# 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)
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))
for decalage in range(self.buy_1_decalage_deb.value, self.buy_1_decalage.value):
if self.buy_0.value:
conditions = list()
condition1, dataframe = condition_generator(
dataframe,
buy_operator0,
buy_indicator0,
buy_crossed_indicator0,
self.buy_1_real_num.value,
self.buy_1_decalage.value
)
conditions.append(condition1)
dataframe.loc[
(
reduce(lambda x, y: x & y, conditions)
& (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= self.buy_1_volume.value)
& (dataframe['sma10'].shift(1) <= dataframe['sma10'])
& (dataframe['close'] < dataframe['bb_middleband'])
& (dataframe['open'] < dataframe['sma10'])
& (dataframe['open'] < dataframe['sma100'])
& (dataframe['min50'].shift(decalage) == dataframe['min50'])
& (dataframe['open'] <= dataframe['min200'] * self.buy_1_min.value)
& (dataframe['percent20'].shift(decalage) <= self.buy_0_percent20.value)
# & (dataframe['min20'] == dataframe['min50'])
& (dataframe['distance_min'] <= self.buy_1_distance.value)
& (dataframe['normal_var_20'] >= self.buy_1_normal_var.value)
), ['buy', 'buy_tag']] = (1, 'buy_1_' + str(decalage))
for decalage in range(self.buy_2_decalage_deb.value, self.buy_2_decalage.value):
if self.buy_2.value:
dataframe.loc[
(
(dataframe['cond1'].shift(decalage) <= 0.45) #self.buy_1_real_num.value / 2)
& (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= self.buy_2_volume.value)
# & (dataframe['sma10'].shift(1) <= dataframe['sma10'])
& (dataframe['close'] < dataframe['sma10'])
& (dataframe['open'] < dataframe['sma100'])
& (dataframe['open'] < dataframe['sma10'])
& (dataframe['min50'].shift(decalage) == dataframe['min50'])
& (dataframe['open'] <= dataframe['min200'] * self.buy_2_min.value)
& (dataframe['percent20'].shift(decalage) <= self.buy_2_percent20.value)
# & (dataframe['min20'] == dataframe['min50'])
& (dataframe['distance_min'] <= self.buy_2_distance.value)
& (dataframe['normal_var_20'] >= self.buy_2_normal_var.value)
), ['buy', 'buy_tag']] = (1, 'buy_2_' + str(decalage))
for decalage in range(self.buy_3_decalage_deb.value, self.buy_3_decalage.value):
if self.buy_3.value:
dataframe.loc[
(
(dataframe['cond1'].shift(decalage) <= 0.2)
& (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= self.buy_3_volume.value)
# & (dataframe['sma10'].shift(1) <= dataframe['sma10'])
& (dataframe['close'] < dataframe['sma10'])
& (dataframe['open'] < dataframe['sma100'])
& (dataframe['open'] < dataframe['sma10'])
& (dataframe['min50'].shift(decalage) == dataframe['min50'])
& (dataframe['open'] <= dataframe['min200'] * self.buy_3_min.value)
& (dataframe['percent20'].shift(decalage) <= self.buy_3_percent20.value)
& (dataframe['distance_min'] <= self.buy_3_distance.value)
& (dataframe['normal_var_20'] >= self.buy_3_normal_var.value)
), ['buy', 'buy_tag']] = (1, 'buy_3_' + str(decalage))
# 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

63
GodStraJD3_7_5_5.json Normal file
View File

@@ -0,0 +1,63 @@
{
"strategy_name": "GodStraJD3_7_5_5",
"params": {
"roi": {
"0": 10
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.026,
"trailing_stop_positive_offset": 0.077,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_0": true,
"buy_0_percent20": 0.03,
"buy_1_cmf100_inf": 0.3,
"buy_1_cmf100_sup": 0.6,
"buy_1_decalage": 7,
"buy_1_decalage_deb": 2,
"buy_1_distance": -0.01,
"buy_1_min": 1.002,
"buy_1_normal_var": 2.2,
"buy_1_real_num": 0.53,
"buy_1_volume": 65,
"buy_2": true,
"buy_2_cmf100_inf": 1.0,
"buy_2_cmf100_sup": 0.0,
"buy_2_decalage": 6,
"buy_2_decalage_deb": 2,
"buy_2_distance": 0.08,
"buy_2_min": 1.025,
"buy_2_normal_var": 1.3,
"buy_2_percent20": -0.09,
"buy_2_real_num": 0.32,
"buy_2_volume": 38,
"buy_3": true,
"buy_3_cmf100_inf": -0.4,
"buy_3_cmf100_sup": -0.1,
"buy_3_decalage": 7,
"buy_3_decalage_deb": 1,
"buy_3_distance": 0.1,
"buy_3_min": 1.016,
"buy_3_normal_var": 1.6,
"buy_3_percent20": 0.03,
"buy_3_real_num": 1.94,
"buy_3_volume": 97,
"buy_min_horizon": 98
},
"sell": {},
"protection": {
"lookback": 133,
"protection_max_allowed_dd": 0.71,
"protection_stop": 61,
"protection_stoploss_stop": 50,
"trade_limit": 9
}
},
"ft_stratparam_v": 1,
"export_time": "2022-03-19 16:02:08.220681+00:00"
}

875
GodStraJD3_7_5_5.py Normal file
View File

@@ -0,0 +1,875 @@
# 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 calendar
from freqtrade.loggers import setup_logging
from technical.indicators import cmf
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
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_5(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'},
'sma10': {'color': 'yellow'},
'min20': {'color': '#87e470'},
'min50': {'color': '#ac3e2a'},
"min1.1": {'color': 'yellow'},
'sma20': {'color': 'cyan'}
},
'subplots': {
# Subplots - each dict defines one additional plot
"BB": {
'bb_width': {'color': 'white'}
},
# "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 = False
profit_old_sma10 = False
profit_over_rsi = True
profit_quick_gain = True
profit_quick_gain_3 = True
profit_quick_lost = False
profit_short_loss = False
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_1_real_num = DecimalParameter(0, 1, decimals=2, default=0.67, space='buy')
buy_2_real_num = DecimalParameter(0, 1, decimals=2, default=0.67, space='buy')
buy_3_real_num = DecimalParameter(0, 2, 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_1_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_1_cmf100_sup = DecimalParameter(-1, 1, decimals=1, default=0.0, space='buy')
buy_2_cmf100_sup = DecimalParameter(-1, 1, decimals=1, default=0.0, space='buy')
buy_3_cmf100_sup = DecimalParameter(-1, 1, decimals=1, default=0.0, space='buy')
buy_1_cmf100_inf = DecimalParameter(-1, 1, decimals=1, default=0.0, space='buy')
buy_2_cmf100_inf = DecimalParameter(-1, 1, decimals=1, default=0.0, space='buy')
buy_3_cmf100_inf = DecimalParameter(-1, 1, decimals=1, default=0.0, space='buy')
buy_1_min = DecimalParameter(1, 1.03, decimals=3, default=1.02, space='buy')
buy_2_min = DecimalParameter(1, 1.03, decimals=3, default=1.02, space='buy')
buy_3_min = DecimalParameter(1, 1.03, decimals=3, default=1.02, space='buy')
buy_1_normal_var = DecimalParameter(0, 5, decimals=1, default=0, space='buy')
buy_2_normal_var = DecimalParameter(0, 5, decimals=1, default=0, space='buy')
buy_3_normal_var = DecimalParameter(0, 5, decimals=1, default=0, space='buy')
buy_1_decalage_deb = IntParameter(1, 3, default=5, space='buy')
buy_2_decalage_deb = IntParameter(1, 3, default=5, space='buy')
buy_3_decalage_deb = IntParameter(1, 3, default=5, space='buy')
buy_1_decalage = IntParameter(buy_1_decalage_deb.value + 1, 8, default=5, space='buy')
buy_2_decalage = IntParameter(buy_2_decalage_deb.value + 1, 8, default=5, space='buy')
buy_3_decalage = IntParameter(buy_3_decalage_deb.value + 1, 8, default=5, space='buy')
buy_1_volume = IntParameter(0, 100, default=10, space='buy')
buy_2_volume = IntParameter(0, 100, default=10, space='buy')
buy_3_volume = IntParameter(0, 100, default=10, 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')
inf_tf = '1h'
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
proposed_stake: float, min_stake: float, max_stake: float,
**kwargs) -> float:
dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
current_candle = dataframe.iloc[-1].squeeze()
# for decalage in range(self.buy_3_decalage_deb.value, self.buy_3_decalage.value):
# decalage_candle = dataframe.iloc[- decalage].squeeze()
# # if (decalage_candle['normal_var_20'] >= 0.6):
# amount = 10 * (- decalage_candle['percent20'] * 100)
# print("use more stake", pair, " ", amount)
# return min(max_stake, amount)
# print("proposed_stake=", proposed_stake, " max_stake=", max_stake)
# if current_candle['bb_width'] > 0.05:
# print("use more stake", pair, " ", proposed_stake * 2)
# return min(max_stake, proposed_stake * 2)
#
# if current_candle['bb_width'] > 0.035:
# print("use more stake", pair, " ", proposed_stake * 1.5)
# return min(max_stake, proposed_stake * 1.5)
# if current_candle['bb_width'] < 0.020:
# print("use less stake", pair, " ", proposed_stake / 2)
# return min(max_stake, proposed_stake / 2)
# if self.config['stake_amount'] == 'unlimited':
# # Use entire available wallet during favorable conditions when in compounding mode.
# return max_stake
# else:
# # Compound profits during favorable conditions instead of using a static stake.
# return self.wallets.get_total_stake_amount() / self.config['max_open_trades']
# Use default stake amount.
return proposed_stake
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
# }
# ]
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 >= -0.01) & ((current_time - trade.open_date_utc).days >= 5)\
& ((current_time - trade.open_date_utc).days < 10)\
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
return "too_old_0.01"
if (current_profit >= -0.02) & ((current_time - trade.open_date_utc).days >= 10)\
& ((current_time - trade.open_date_utc).days < 15) \
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
return "too_old_0.02"
if (current_profit >= -0.03) & ((current_time - trade.open_date_utc).days >= 15) \
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
return "too_old_0.03"
if self.profit_quick_lost:
if (current_profit >= 0) & (last_candle['percent3'] < -0.015):
return "quick_lost"
if self.profit_no_change:
if (current_profit > 0.005) & (last_candle['percent10'] < 0.001) & (last_candle['percent5'] < 0) & ((current_time - trade.open_date_utc).seconds >= 3600):
return "no_change"
if (current_profit > 0.005) & (last_candle['normal_var_20'] < 0.008):
return "no_change_20"
if (current_profit > 0.01) & (last_candle['normal_var_10'] < 0.008):
return "no_change_10"
if (current_profit > 0.01) & (last_candle['normal_var_5'] < 0.005):
return "no_change_5"
#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 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'] > 88): # & (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'] > 82) & (last_candle['percent'] < -0.02): #| (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, self.inf_tf) for pair in pairs]
# Optionally Add additional "static" pairs
# informative_pairs += [("ETH/USDT", "5m"), ("BTC/TUSD", "15m")]
return informative_pairs
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# dataframe['profit'] = 0
# RSI
dataframe['rsi'] = ta.RSI(dataframe)
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_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_5'] = dataframe['normal'].rolling(5).var()
dataframe['normal_var_10'] = dataframe['normal'].rolling(10).var()
dataframe['normal_var_20'] = dataframe['normal'].rolling(20).var()
dataframe['normal_var_50'] = dataframe['normal'].rolling(50).var()
# 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['cmf20'] = cmf(dataframe, 20)
dataframe['cmf50'] = cmf(dataframe, 50)
dataframe['cmf100'] = cmf(dataframe, 100)
# 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=self.inf_tf)
# Get the 14 day rsi
informative['rsi'] = ta.RSI(informative, timeperiod=14)
# informative['cmf'] = cmf(informative, timeperiod=14)
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])
pandas.set_option('display.max_rows', informative.shape[0] + 1)
pandas.set_option('display.max_columns', 50)
print('informative', metadata['pair'], informative.tail(1))
# Use the helper function merge_informative_pair to safely merge the pair
# Automatically renames the columns and merges a shorter timeframe dataframe and a longer timeframe informative pair
# use ffill to have the 1d value available in every row throughout the day.
# Without this, comparisons between columns of the original and the informative pair would only work once per day.
# Full documentation of this method, see below
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, self.inf_tf, 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))
# for decalage in range(self.buy_1_decalage_deb.value, self.buy_1_decalage.value):
# if self.buy_0.value:
# conditions = list()
# condition1, dataframe = condition_generator(
# dataframe,
# buy_operator0,
# buy_indicator0,
# buy_crossed_indicator0,
# self.buy_1_real_num.value,
# self.buy_1_decalage.value
# )
# conditions.append(condition1)
# dataframe.loc[
# (
# reduce(lambda x, y: x & y, conditions)
# & (dataframe['cmf100'] < self.buy_1_cmf100_sup.value)
# & (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= self.buy_1_volume.value)
# & (dataframe['sma10'].shift(1) <= dataframe['sma10'])
# & (dataframe['close'] < dataframe['bb_middleband'])
# & (dataframe['open'] < dataframe['sma10'])
# & (dataframe['open'] < dataframe['sma100'])
# & (dataframe['min50'].shift(decalage) == dataframe['min50'])
# & (dataframe['open'] <= dataframe['min200'] * self.buy_1_min.value)
# & (dataframe['percent20'].shift(decalage) <= self.buy_0_percent20.value)
# # & (dataframe['min20'] == dataframe['min50'])
# & (dataframe['distance_min'] <= self.buy_1_distance.value)
# & (dataframe['normal_var_20'] >= self.buy_1_normal_var.value)
# ), ['buy', 'buy_tag']] = (1, 'buy_1_' + str(decalage))
for decalage in range(self.buy_2_decalage_deb.value, self.buy_2_decalage.value):
if self.buy_2.value:
dataframe.loc[
(
(dataframe['cond1'].shift(decalage) <= 0.45) #self.buy_2_real_num.value)
& (dataframe['cmf100'] >= self.buy_2_cmf100_sup.value)
& (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= self.buy_2_volume.value)
# & (dataframe['sma10'].shift(1) <= dataframe['sma10'])
& (dataframe['close'] < dataframe['sma10'])
& (dataframe['open'] < dataframe['sma100'])
& (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['normal_var_20'] >= self.buy_2_normal_var.value)
), ['buy', 'buy_tag']] = (1, 'buy_2_' + str(decalage))
for decalage in range(self.buy_3_decalage_deb.value, self.buy_3_decalage.value):
if self.buy_3.value:
dataframe.loc[
(
(dataframe['cond1'].shift(decalage) <= 0.2) #self.buy_3_real_num.value)
& (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= self.buy_3_volume.value)
# & (dataframe['sma10'].shift(1) <= dataframe['sma10'])
& (dataframe['cmf100'] < self.buy_3_cmf100_sup.value)
# & (dataframe['cmf100'] > self.buy_3_cmf100_inf.value)
& (dataframe['close'] < dataframe['sma10'])
& (dataframe['open'] < dataframe['sma100'])
& (dataframe['open'] < dataframe['sma10'])
& (dataframe['min50'].shift(decalage) == dataframe['min50'])
# & (dataframe['open'] <= dataframe['min200'] * self.buy_3_min.value)
& (dataframe['percent20'].shift(decalage) <= self.buy_3_percent20.value)
& (dataframe['distance_min'] <= self.buy_3_distance.value)
# & (dataframe['normal_var_20'] >= self.buy_3_normal_var.value)
), ['buy', 'buy_tag']] = (1, 'buy_3_' + str(decalage))
# 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

48
GodStraJD3_7_5_6.json Normal file
View File

@@ -0,0 +1,48 @@
{
"strategy_name": "GodStraJD3_7_5_6",
"params": {
"roi": {
"0": 10
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.026,
"trailing_stop_positive_offset": 0.077,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_0": true,
"buy_0_percent20": 0.08,
"buy_1_volume": 0,
"buy_3": true,
"buy_3_cmf100_inf": 0.4,
"buy_3_cmf100_sup": -0.6,
"buy_3_cond_1h_num": 0.56,
"buy_3_cond_num": 0.76,
"buy_3_decalage": 7,
"buy_3_decalage_deb": 3,
"buy_3_distance": 0.08,
"buy_3_min": 1.016,
"buy_3_normal_var": 3.3,
"buy_3_percent20": 0.1,
"buy_3_percent_1d_num": 0.01,
"buy_3_percent_1w_num": -0.04,
"buy_3_real_num": 0.23,
"buy_3_volume": 96,
"buy_min_horizon": 198
},
"sell": {},
"protection": {
"lookback": 133,
"protection_max_allowed_dd": 0.71,
"protection_stop": 61,
"protection_stoploss_stop": 50,
"trade_limit": 9
}
},
"ft_stratparam_v": 1,
"export_time": "2022-03-22 20:30:50.351361+00:00"
}

898
GodStraJD3_7_5_6.py Normal file
View File

@@ -0,0 +1,898 @@
# 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 calendar
from freqtrade.loggers import setup_logging
from technical.indicators import cmf
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
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_6(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'},
'sma10': {'color': 'yellow'},
'min20': {'color': '#87e470'},
'min50': {'color': '#ac3e2a'},
"min1.1": {'color': 'yellow'},
'sma20': {'color': 'cyan'}
},
'subplots': {
# Subplots - each dict defines one additional plot
"BB": {
'bb_width': {'color': 'white'}
},
# "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 = False
profit_old_sma10 = False
profit_over_rsi = True
profit_quick_gain = True
profit_quick_gain_3 = True
profit_quick_lost = False
profit_short_loss = False
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_1_cond_num = DecimalParameter(0, 2, decimals=2, default=0.67, space='buy')
# buy_2_cond_num = DecimalParameter(0, 2, decimals=2, default=0.67, space='buy')
buy_3_cond_num = DecimalParameter(0, 2, decimals=2, default=0.67, space='buy')
# buy_1_cond_1h_num = DecimalParameter(0, 2, decimals=2, default=0.67, space='buy')
# buy_2_cond_1h_num = DecimalParameter(0, 2, decimals=2, default=0.67, space='buy')
buy_3_cond_1h_num = DecimalParameter(0, 2, 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_1_real_num = DecimalParameter(0, 1, decimals=2, default=0.67, space='buy')
# buy_2_real_num = DecimalParameter(0, 1, decimals=2, default=0.67, space='buy')
buy_3_real_num = DecimalParameter(0, 2, 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_1_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_1_cmf100_sup = DecimalParameter(-1, 1, decimals=1, default=0.0, space='buy')
# buy_2_cmf100_sup = DecimalParameter(-1, 1, decimals=1, default=0.0, space='buy')
buy_3_cmf100_sup = DecimalParameter(-1, 1, decimals=1, default=0.0, space='buy')
# buy_1_cmf100_inf = DecimalParameter(-1, 1, decimals=1, default=0.0, space='buy')
# buy_2_cmf100_inf = DecimalParameter(-1, 1, decimals=1, default=0.0, space='buy')
buy_3_cmf100_inf = DecimalParameter(-1, 1, decimals=1, default=0.0, space='buy')
# buy_1_min = DecimalParameter(1, 1.03, decimals=3, default=1.02, space='buy')
# buy_2_min = DecimalParameter(1, 1.03, decimals=3, default=1.02, space='buy')
buy_3_min = DecimalParameter(1, 1.03, decimals=3, default=1.02, space='buy')
# buy_1_normal_var = DecimalParameter(0, 5, decimals=1, default=0, space='buy')
# buy_2_normal_var = DecimalParameter(0, 5, decimals=1, default=0, space='buy')
buy_3_normal_var = DecimalParameter(0, 5, decimals=1, default=0, space='buy')
# buy_1_decalage_deb = IntParameter(1, 3, default=5, space='buy')
# buy_2_decalage_deb = IntParameter(1, 3, default=5, space='buy')
buy_3_decalage_deb = IntParameter(1, 3, default=5, space='buy')
# buy_1_decalage = IntParameter(buy_1_decalage_deb.value + 1, 8, default=5, space='buy')
# buy_2_decalage = IntParameter(# buy_2_decalage_deb.value + 1, 8, default=5, space='buy')
buy_3_decalage = IntParameter(buy_3_decalage_deb.value + 1, 8, default=5, space='buy')
buy_1_volume = IntParameter(0, 100, default=10, space='buy')
# buy_2_volume = IntParameter(0, 100, default=10, space='buy')
buy_3_volume = IntParameter(0, 100, default=10, 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')
inf_tf = '4h'
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
proposed_stake: float, min_stake: float, max_stake: float,
**kwargs) -> float:
dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
current_candle = dataframe.iloc[-1].squeeze()
# for decalage in range(self.buy_3_decalage_deb.value, self.buy_3_decalage.value):
# decalage_candle = dataframe.iloc[- decalage].squeeze()
# # if (decalage_candle['normal_var_20'] >= 0.6):
# amount = 10 * (- decalage_candle['percent20'] * 100)
# print("use more stake", pair, " ", amount)
# return min(max_stake, amount)
# print("proposed_stake=", proposed_stake, " max_stake=", max_stake)
# if current_candle['bb_width'] > 0.05:
# print("use more stake", pair, " ", proposed_stake * 2)
# return min(max_stake, proposed_stake * 2)
#
# if current_candle['bb_width'] > 0.035:
# print("use more stake", pair, " ", proposed_stake * 1.5)
# return min(max_stake, proposed_stake * 1.5)
# if current_candle['bb_width'] < 0.020:
# print("use less stake", pair, " ", proposed_stake / 2)
# return min(max_stake, proposed_stake / 2)
# if self.config['stake_amount'] == 'unlimited':
# # Use entire available wallet during favorable conditions when in compounding mode.
# return max_stake
# else:
# # Compound profits during favorable conditions instead of using a static stake.
# return self.wallets.get_total_stake_amount() / self.config['max_open_trades']
# Use default stake amount.
return proposed_stake
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
# }
# ]
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 >= -0.01) & ((current_time - trade.open_date_utc).days >= 5)\
& ((current_time - trade.open_date_utc).days < 10)\
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
return "too_old_0.01"
if (current_profit >= -0.02) & ((current_time - trade.open_date_utc).days >= 10)\
& ((current_time - trade.open_date_utc).days < 15) \
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
return "too_old_0.02"
if (current_profit >= -0.03) & ((current_time - trade.open_date_utc).days >= 15) \
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
return "too_old_0.03"
if self.profit_quick_lost:
if (current_profit >= 0) & (last_candle['percent3'] < -0.015):
return "quick_lost"
if self.profit_no_change:
if (current_profit > 0.005) & (last_candle['percent10'] < 0.001) & (last_candle['percent5'] < 0) & ((current_time - trade.open_date_utc).seconds >= 3600):
return "no_change"
if (current_profit > 0.005) & (last_candle['normal_var_20'] < 0.008):
return "no_change_20"
if (current_profit > 0.01) & (last_candle['normal_var_10'] < 0.008):
return "no_change_10"
if (current_profit > 0.01) & (last_candle['normal_var_5'] < 0.005):
return "no_change_5"
#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 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'] > 88): # & (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'] > 82) & (last_candle['percent'] < -0.02): #| (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, self.inf_tf) 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 += [("ETH/USDT", "5m"), ("BTC/TUSD", "15m")]
return informative_pairs
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# dataframe['profit'] = 0
# RSI
dataframe['rsi'] = ta.RSI(dataframe)
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'].rolling(5).var()
# 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_5'] = dataframe['normal'].rolling(5).var()
dataframe['normal_var_10'] = dataframe['normal'].rolling(10).var()
dataframe['normal_var_20'] = dataframe['normal'].rolling(20).var()
dataframe['normal_var_50'] = dataframe['normal'].rolling(50).var()
# 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['cmf20'] = cmf(dataframe, 20)
dataframe['cmf50'] = cmf(dataframe, 50)
dataframe['cmf100'] = cmf(dataframe, 100)
# 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=self.inf_tf)
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])
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, self.inf_tf, 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["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))
# for decalage in range(self.buy_1_decalage_deb.value, self.buy_1_decalage.value):
# if self.buy_0.value:
# conditions = list()
# condition1, dataframe = condition_generator(
# dataframe,
# buy_operator0,
# buy_indicator0,
# buy_crossed_indicator0,
# self.buy_1_real_num.value,
# self.buy_1_decalage.value
# )
# conditions.append(condition1)
# dataframe.loc[
# (
# reduce(lambda x, y: x & y, conditions)
# & (dataframe['cmf100'] < self.buy_1_cmf100_sup.value)
# & (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= self.buy_1_volume.value)
# & (dataframe['sma10'].shift(1) <= dataframe['sma10'])
# & (dataframe['close'] < dataframe['bb_middleband'])
# & (dataframe['open'] < dataframe['sma10'])
# & (dataframe['open'] < dataframe['sma100'])
# & (dataframe['min50'].shift(decalage) == dataframe['min50'])
# & (dataframe['open'] <= dataframe['min200'] * self.buy_1_min.value)
# & (dataframe['percent20'].shift(decalage) <= self.buy_0_percent20.value)
# # & (dataframe['min20'] == dataframe['min50'])
# & (dataframe['distance_min'] <= self.buy_1_distance.value)
# & (dataframe['normal_var_20'] >= self.buy_1_normal_var.value)
# ), ['buy', 'buy_tag']] = (1, 'buy_1_' + str(decalage))
# for decalage in range(self.buy_2_decalage_deb.value, self.buy_2_decalage.value):
# if self.buy_2.value:
# dataframe.loc[
# (
# (dataframe['cond1'].shift(decalage) <= self.buy_2_cond_num.value)
# & (dataframe['cond1'].shift(decalage) >= self.buy_3_cond_num.value)
# & (dataframe['cond1_1h'] <= self.buy_2_cond_1h_num.value)
# & (dataframe['cmf100'] >= self.buy_2_cmf100_sup.value)
# & (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= self.buy_2_volume.value)
# # & (dataframe['sma10'].shift(1) <= dataframe['sma10'])
# & (dataframe['close'] < dataframe['sma10'])
# & (dataframe['open'] < dataframe['sma100'])
# & (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['normal_var_20'] >= self.buy_2_normal_var.value)
# ), ['buy', 'buy_tag']] = (1, 'buy_2_' + str(decalage))
for decalage in range(self.buy_3_decalage_deb.value, self.buy_3_decalage.value):
if self.buy_3.value:
dataframe.loc[
(
(dataframe['cond1'].shift(decalage) <= self.buy_3_cond_num.value)
#& (dataframe['percent_1d'] <= self.buy_3_percent_1d_num.value)
#& (dataframe['percent_1w'] <= self.buy_3_percent_1w_num.value)
& (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= self.buy_3_volume.value)
# & (dataframe['sma10'].shift(1) <= dataframe['sma10'])
# & (dataframe['cmf100'] < self.buy_3_cmf100_sup.value)
# & (dataframe['cmf100'] > self.buy_3_cmf100_inf.value)
# & (dataframe['cmf100'] > self.buy_3_cmf100_inf.value)
& (dataframe['close'] < dataframe['sma10'])
& (dataframe['open'] < dataframe['sma20'])
& (dataframe['open'] < dataframe['sma10'])
& (dataframe['min50'].shift(decalage) == dataframe['min50'])
# & (dataframe['open'] <= dataframe['min200'] * self.buy_3_min.value)
& (dataframe['percent20'].shift(decalage) <= self.buy_3_percent20.value)
& (dataframe['distance_min'] <= self.buy_3_distance.value)
# & (dataframe['normal_var_20'] >= self.buy_3_normal_var.value)
), ['buy', 'buy_tag']] = (1, 'buy_3_' + str(decalage))
# 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

63
GodStraJD3_7_5_7.json Normal file
View File

@@ -0,0 +1,63 @@
{
"strategy_name": "GodStraJD3_7_5_7",
"params": {
"roi": {
"0": 10
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.026,
"trailing_stop_positive_offset": 0.077,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_0": true,
"buy_0_percent20": 0.05,
"buy_1_cmf100_inf": 0.5,
"buy_1_cmf100_sup": -0.6,
"buy_1_decalage": 6,
"buy_1_decalage_deb": 2,
"buy_1_distance": 0.1,
"buy_1_min": 1.01,
"buy_1_normal_var": 1.0,
"buy_1_real_num": 0.01,
"buy_1_volume": 60,
"buy_2": true,
"buy_2_cmf100_inf": -0.9,
"buy_2_cmf100_sup": -1.0,
"buy_2_decalage": 7,
"buy_2_decalage_deb": 1,
"buy_2_distance": 0.09,
"buy_2_min": 1.025,
"buy_2_normal_var": 4.0,
"buy_2_percent20": 0.06,
"buy_2_real_num": 0.61,
"buy_2_volume": 33,
"buy_3": false,
"buy_3_cmf100_inf": 0.0,
"buy_3_cmf100_sup": 0.7,
"buy_3_decalage": 7,
"buy_3_decalage_deb": 3,
"buy_3_distance": -0.06,
"buy_3_min": 1.006,
"buy_3_normal_var": 4.5,
"buy_3_percent20": 0.1,
"buy_3_real_num": 1.41,
"buy_3_volume": 15,
"buy_min_horizon": 197
},
"sell": {},
"protection": {
"lookback": 133,
"protection_max_allowed_dd": 0.71,
"protection_stop": 61,
"protection_stoploss_stop": 50,
"trade_limit": 9
}
},
"ft_stratparam_v": 1,
"export_time": "2022-03-20 19:38:37.829599+00:00"
}

878
GodStraJD3_7_5_7.py Normal file
View File

@@ -0,0 +1,878 @@
# 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 calendar
from freqtrade.loggers import setup_logging
from technical.indicators import cmf
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
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_7(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'},
'sma10': {'color': 'yellow'},
'min20': {'color': '#87e470'},
'min50': {'color': '#ac3e2a'},
"min1.1": {'color': 'yellow'},
'sma20': {'color': 'cyan'}
},
'subplots': {
# Subplots - each dict defines one additional plot
"BB": {
'bb_width': {'color': 'white'}
},
# "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 = False
profit_old_sma10 = False
profit_over_rsi = True
profit_quick_gain = True
profit_quick_gain_3 = True
profit_quick_lost = False
profit_short_loss = False
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_1_real_num = DecimalParameter(0, 1, decimals=2, default=0.67, space='buy')
buy_2_real_num = DecimalParameter(0, 1, decimals=2, default=0.67, space='buy')
buy_3_real_num = DecimalParameter(0, 2, 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_1_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_1_cmf100_sup = DecimalParameter(-1, 1, decimals=1, default=0.0, space='buy')
buy_2_cmf100_sup = DecimalParameter(-1, 1, decimals=1, default=0.0, space='buy')
buy_3_cmf100_sup = DecimalParameter(-1, 1, decimals=1, default=0.0, space='buy')
buy_1_cmf100_inf = DecimalParameter(-1, 1, decimals=1, default=0.0, space='buy')
buy_2_cmf100_inf = DecimalParameter(-1, 1, decimals=1, default=0.0, space='buy')
buy_3_cmf100_inf = DecimalParameter(-1, 1, decimals=1, default=0.0, space='buy')
buy_1_min = DecimalParameter(1, 1.03, decimals=3, default=1.02, space='buy')
buy_2_min = DecimalParameter(1, 1.03, decimals=3, default=1.02, space='buy')
buy_3_min = DecimalParameter(1, 1.03, decimals=3, default=1.02, space='buy')
buy_1_normal_var = DecimalParameter(0, 5, decimals=1, default=0, space='buy')
buy_2_normal_var = DecimalParameter(0, 5, decimals=1, default=0, space='buy')
buy_3_normal_var = DecimalParameter(0, 5, decimals=1, default=0, space='buy')
buy_1_decalage_deb = IntParameter(1, 3, default=5, space='buy')
buy_2_decalage_deb = IntParameter(1, 3, default=5, space='buy')
buy_3_decalage_deb = IntParameter(1, 3, default=5, space='buy')
buy_1_decalage = IntParameter(buy_1_decalage_deb.value + 1, 8, default=5, space='buy')
buy_2_decalage = IntParameter(buy_2_decalage_deb.value + 1, 8, default=5, space='buy')
buy_3_decalage = IntParameter(buy_3_decalage_deb.value + 1, 8, default=5, space='buy')
buy_1_volume = IntParameter(0, 100, default=10, space='buy')
buy_2_volume = IntParameter(0, 100, default=10, space='buy')
buy_3_volume = IntParameter(0, 100, default=10, 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')
inf_tf = '1h'
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
proposed_stake: float, min_stake: float, max_stake: float,
**kwargs) -> float:
dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
current_candle = dataframe.iloc[-1].squeeze()
# for decalage in range(self.buy_3_decalage_deb.value, self.buy_3_decalage.value):
# decalage_candle = dataframe.iloc[- decalage].squeeze()
# # if (decalage_candle['normal_var_20'] >= 0.6):
# amount = 10 * (- decalage_candle['percent20'] * 100)
# print("use more stake", pair, " ", amount)
# return min(max_stake, amount)
# print("proposed_stake=", proposed_stake, " max_stake=", max_stake)
# if current_candle['bb_width'] > 0.05:
# print("use more stake", pair, " ", proposed_stake * 2)
# return min(max_stake, proposed_stake * 2)
#
# if current_candle['bb_width'] > 0.035:
# print("use more stake", pair, " ", proposed_stake * 1.5)
# return min(max_stake, proposed_stake * 1.5)
# if current_candle['bb_width'] < 0.020:
# print("use less stake", pair, " ", proposed_stake / 2)
# return min(max_stake, proposed_stake / 2)
# if self.config['stake_amount'] == 'unlimited':
# # Use entire available wallet during favorable conditions when in compounding mode.
# return max_stake
# else:
# # Compound profits during favorable conditions instead of using a static stake.
# return self.wallets.get_total_stake_amount() / self.config['max_open_trades']
# Use default stake amount.
return proposed_stake
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
# }
# ]
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 >= -0.01) & ((current_time - trade.open_date_utc).days >= 5)\
& ((current_time - trade.open_date_utc).days < 10)\
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
return "too_old_0.01"
if (current_profit >= -0.02) & ((current_time - trade.open_date_utc).days >= 10)\
& ((current_time - trade.open_date_utc).days < 15) \
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
return "too_old_0.02"
if (current_profit >= -0.03) & ((current_time - trade.open_date_utc).days >= 15) \
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
return "too_old_0.03"
if self.profit_quick_lost:
if (current_profit >= 0) & (last_candle['percent3'] < -0.015):
return "quick_lost"
if self.profit_no_change:
if (current_profit > 0.005) & (last_candle['percent10'] < 0.001) & (last_candle['percent5'] < 0) & ((current_time - trade.open_date_utc).seconds >= 3600):
return "no_change"
if (current_profit > 0.005) & (last_candle['normal_var_20'] < 0.008):
return "no_change_20"
if (current_profit > 0.01) & (last_candle['normal_var_10'] < 0.008):
return "no_change_10"
if (current_profit > 0.01) & (last_candle['normal_var_5'] < 0.005):
return "no_change_5"
#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 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['percent3'] < 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'] > 88): # & (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'] > 82) & (last_candle['percent'] < -0.02): #| (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, self.inf_tf) for pair in pairs]
# Optionally Add additional "static" pairs
# informative_pairs += [("ETH/USDT", "5m"), ("BTC/TUSD", "15m")]
return informative_pairs
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# dataframe['profit'] = 0
# RSI
dataframe['rsi'] = ta.RSI(dataframe)
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_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_5'] = dataframe['normal'].rolling(5).var()
dataframe['normal_var_10'] = dataframe['normal'].rolling(10).var()
dataframe['normal_var_20'] = dataframe['normal'].rolling(20).var()
dataframe['normal_var_50'] = dataframe['normal'].rolling(50).var()
# 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['cmf20'] = cmf(dataframe, 20)
dataframe['cmf50'] = cmf(dataframe, 50)
dataframe['cmf100'] = cmf(dataframe, 100)
# 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=self.inf_tf)
# Get the 14 day rsi
informative['rsi'] = ta.RSI(informative, timeperiod=14)
# informative['cmf'] = cmf(informative, timeperiod=14)
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])
pandas.set_option('display.max_rows', informative.shape[0] + 1)
pandas.set_option('display.max_columns', 50)
# print('informative', metadata['pair'], informative.tail(1))
# Use the helper function merge_informative_pair to safely merge the pair
# Automatically renames the columns and merges a shorter timeframe dataframe and a longer timeframe informative pair
# use ffill to have the 1d value available in every row throughout the day.
# Without this, comparisons between columns of the original and the informative pair would only work once per day.
# Full documentation of this method, see below
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, self.inf_tf, 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))
# for decalage in range(self.buy_1_decalage_deb.value, self.buy_1_decalage.value):
# if self.buy_0.value:
# conditions = list()
# condition1, dataframe = condition_generator(
# dataframe,
# buy_operator0,
# buy_indicator0,
# buy_crossed_indicator0,
# self.buy_1_real_num.value,
# self.buy_1_decalage.value
# )
# conditions.append(condition1)
# dataframe.loc[
# (
# reduce(lambda x, y: x & y, conditions)
# & (dataframe['cmf100'] < self.buy_1_cmf100_sup.value)
# & (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= self.buy_1_volume.value)
# & (dataframe['sma10'].shift(1) <= dataframe['sma10'])
# & (dataframe['close'] < dataframe['bb_middleband'])
# & (dataframe['open'] < dataframe['sma10'])
# & (dataframe['open'] < dataframe['sma100'])
# & (dataframe['min50'].shift(decalage) == dataframe['min50'])
# & (dataframe['open'] <= dataframe['min200'] * self.buy_1_min.value)
# & (dataframe['percent20'].shift(decalage) <= self.buy_0_percent20.value)
# # & (dataframe['min20'] == dataframe['min50'])
# & (dataframe['distance_min'] <= self.buy_1_distance.value)
# & (dataframe['normal_var_20'] >= self.buy_1_normal_var.value)
# ), ['buy', 'buy_tag']] = (1, 'buy_1_' + str(decalage))
for decalage in range(self.buy_2_decalage_deb.value, self.buy_2_decalage.value):
if self.buy_2.value:
dataframe.loc[
(
(dataframe['cond1'].shift(decalage) <= 0.45) #self.buy_2_real_num.value)
& (dataframe['cond1_1h'] <= self.buy_2_real_num.value)
& (dataframe['cmf100'] >= self.buy_2_cmf100_sup.value)
& (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= self.buy_2_volume.value)
# & (dataframe['sma10'].shift(1) <= dataframe['sma10'])
& (dataframe['close'] < dataframe['sma10'])
& (dataframe['open'] < dataframe['sma100'])
& (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['normal_var_20'] >= self.buy_2_normal_var.value)
), ['buy', 'buy_tag']] = (1, 'buy_2_' + str(decalage))
for decalage in range(self.buy_3_decalage_deb.value, self.buy_3_decalage.value):
if self.buy_3.value:
dataframe.loc[
(
(dataframe['cond1'].shift(decalage) <= 0.2) #self.buy_3_real_num.value)
& (dataframe['cond1_1h'] <= self.buy_3_real_num.value)
& (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= self.buy_3_volume.value)
# & (dataframe['sma10'].shift(1) <= dataframe['sma10'])
& (dataframe['cmf100'] < self.buy_3_cmf100_sup.value)
# & (dataframe['cmf100'] > self.buy_3_cmf100_inf.value)
& (dataframe['close'] < dataframe['sma10'])
& (dataframe['open'] < dataframe['sma100'])
& (dataframe['open'] < dataframe['sma10'])
& (dataframe['min50'].shift(decalage) == dataframe['min50'])
# & (dataframe['open'] <= dataframe['min200'] * self.buy_3_min.value)
& (dataframe['percent20'].shift(decalage) <= self.buy_3_percent20.value)
& (dataframe['distance_min'] <= self.buy_3_distance.value)
# & (dataframe['normal_var_20'] >= self.buy_3_normal_var.value)
), ['buy', 'buy_tag']] = (1, 'buy_3_' + str(decalage))
# 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

46
GodStraJD3_7_5_8.json Normal file
View File

@@ -0,0 +1,46 @@
{
"strategy_name": "GodStraJD3_7_5_8",
"params": {
"roi": {
"0": 10
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.026,
"trailing_stop_positive_offset": 0.077,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_0": true,
"buy_0_percent20": -0.07,
"buy_1_volume": 43,
"buy_3": true,
"buy_3_cmf100_inf": -0.9,
"buy_3_cmf100_sup": 1.0,
"buy_3_cond_1h_num": 0.37,
"buy_3_cond_num": 1.78,
"buy_3_decalage": 8,
"buy_3_decalage_deb": 1,
"buy_3_distance": 0.1,
"buy_3_min": 1.022,
"buy_3_normal_var": 2.1,
"buy_3_percent20": 0.09,
"buy_3_real_num": 0.37,
"buy_3_volume": 60,
"buy_min_horizon": 58
},
"sell": {},
"protection": {
"lookback": 133,
"protection_max_allowed_dd": 0.71,
"protection_stop": 61,
"protection_stoploss_stop": 50,
"trade_limit": 9
}
},
"ft_stratparam_v": 1,
"export_time": "2022-03-20 17:59:02.967586+00:00"
}

889
GodStraJD3_7_5_8.py Normal file
View File

@@ -0,0 +1,889 @@
# 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 calendar
from freqtrade.loggers import setup_logging
from technical.indicators import cmf
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
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_8(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'},
'sma10': {'color': 'yellow'},
'min20': {'color': '#87e470'},
'min50': {'color': '#ac3e2a'},
"min1.1": {'color': 'yellow'},
'sma20': {'color': 'cyan'}
},
'subplots': {
# Subplots - each dict defines one additional plot
"BB": {
'bb_width': {'color': 'white'}
},
# "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 = False
profit_old_sma10 = False
profit_over_rsi = True
profit_quick_gain = True
profit_quick_gain_3 = True
profit_quick_lost = False
profit_short_loss = False
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_1_cond_num = DecimalParameter(0, 2, decimals=2, default=0.67, space='buy')
# buy_2_cond_num = DecimalParameter(0, 2, decimals=2, default=0.67, space='buy')
buy_3_cond_num = DecimalParameter(0, 2, decimals=2, default=0.67, space='buy')
# buy_1_cond_1h_num = DecimalParameter(0, 2, decimals=2, default=0.67, space='buy')
# buy_2_cond_1h_num = DecimalParameter(0, 2, decimals=2, default=0.67, space='buy')
buy_3_cond_1h_num = DecimalParameter(0, 2, decimals=2, default=0.67, space='buy')
# buy_1_real_num = DecimalParameter(0, 1, decimals=2, default=0.67, space='buy')
# buy_2_real_num = DecimalParameter(0, 1, decimals=2, default=0.67, space='buy')
buy_3_real_num = DecimalParameter(0, 2, 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_1_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_1_cmf100_sup = DecimalParameter(-1, 1, decimals=1, default=0.0, space='buy')
# buy_2_cmf100_sup = DecimalParameter(-1, 1, decimals=1, default=0.0, space='buy')
buy_3_cmf100_sup = DecimalParameter(-1, 1, decimals=1, default=0.0, space='buy')
# buy_1_cmf100_inf = DecimalParameter(-1, 1, decimals=1, default=0.0, space='buy')
# buy_2_cmf100_inf = DecimalParameter(-1, 1, decimals=1, default=0.0, space='buy')
buy_3_cmf100_inf = DecimalParameter(-1, 1, decimals=1, default=0.0, space='buy')
# buy_1_min = DecimalParameter(1, 1.03, decimals=3, default=1.02, space='buy')
# buy_2_min = DecimalParameter(1, 1.03, decimals=3, default=1.02, space='buy')
buy_3_min = DecimalParameter(1, 1.03, decimals=3, default=1.02, space='buy')
# buy_1_normal_var = DecimalParameter(0, 5, decimals=1, default=0, space='buy')
# buy_2_normal_var = DecimalParameter(0, 5, decimals=1, default=0, space='buy')
buy_3_normal_var = DecimalParameter(0, 5, decimals=1, default=0, space='buy')
# buy_1_decalage_deb = IntParameter(1, 3, default=5, space='buy')
# buy_2_decalage_deb = IntParameter(1, 3, default=5, space='buy')
buy_3_decalage_deb = IntParameter(1, 3, default=5, space='buy')
# buy_1_decalage = IntParameter(buy_1_decalage_deb.value + 1, 8, default=5, space='buy')
# buy_2_decalage = IntParameter(# buy_2_decalage_deb.value + 1, 8, default=5, space='buy')
buy_3_decalage = IntParameter(buy_3_decalage_deb.value + 1, 8, default=5, space='buy')
buy_1_volume = IntParameter(0, 100, default=10, space='buy')
# buy_2_volume = IntParameter(0, 100, default=10, space='buy')
buy_3_volume = IntParameter(0, 100, default=10, 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')
inf_tf = '1h'
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
proposed_stake: float, min_stake: float, max_stake: float,
**kwargs) -> float:
dataframe, _ = self.dp.get_analyzed_dataframe(pair=pair, timeframe=self.timeframe)
current_candle = dataframe.iloc[-1].squeeze()
# for decalage in range(self.buy_3_decalage_deb.value, self.buy_3_decalage.value):
# decalage_candle = dataframe.iloc[- decalage].squeeze()
# # if (decalage_candle['normal_var_20'] >= 0.6):
# amount = 10 * (- decalage_candle['percent20'] * 100)
# print("use more stake", pair, " ", amount)
# return min(max_stake, amount)
# print("proposed_stake=", proposed_stake, " max_stake=", max_stake)
# if current_candle['bb_width'] > 0.05:
# print("use more stake", pair, " ", proposed_stake * 2)
# return min(max_stake, proposed_stake * 2)
#
# if current_candle['bb_width'] > 0.035:
# print("use more stake", pair, " ", proposed_stake * 1.5)
# return min(max_stake, proposed_stake * 1.5)
# if current_candle['bb_width'] < 0.020:
# print("use less stake", pair, " ", proposed_stake / 2)
# return min(max_stake, proposed_stake / 2)
# if self.config['stake_amount'] == 'unlimited':
# # Use entire available wallet during favorable conditions when in compounding mode.
# return max_stake
# else:
# # Compound profits during favorable conditions instead of using a static stake.
# return self.wallets.get_total_stake_amount() / self.config['max_open_trades']
# Use default stake amount.
return proposed_stake
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
# }
# ]
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 >= -0.01) & ((current_time - trade.open_date_utc).days >= 5)\
& ((current_time - trade.open_date_utc).days < 10)\
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
return "too_old_0.01"
if (current_profit >= -0.02) & ((current_time - trade.open_date_utc).days >= 10)\
& ((current_time - trade.open_date_utc).days < 15) \
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
return "too_old_0.02"
if (current_profit >= -0.03) & ((current_time - trade.open_date_utc).days >= 15) \
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
return "too_old_0.03"
if self.profit_quick_lost:
if (current_profit >= 0) & (last_candle['percent3'] < -0.015):
return "quick_lost"
if self.profit_no_change:
if (current_profit > 0.005) & (last_candle['percent10'] < 0.001) & (last_candle['percent5'] < 0) & ((current_time - trade.open_date_utc).seconds >= 3600):
return "no_change"
if (current_profit > 0.005) & (last_candle['normal_var_20'] < 0.008):
return "no_change_20"
if (current_profit > 0.01) & (last_candle['normal_var_10'] < 0.008):
return "no_change_10"
if (current_profit > 0.01) & (last_candle['normal_var_5'] < 0.005):
return "no_change_5"
#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):
return "quick_gain_3"
if self.profit_quick_gain:
if (0.01 < current_profit < 0.03) & (last_candle['percent3'] < 0):
return "quick_gain"
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'] > 88): # & (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'] > 82) & (last_candle['percent'] < -0.02): #| (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, self.inf_tf) for pair in pairs]
# Optionally Add additional "static" pairs
# informative_pairs += [("ETH/USDT", "5m"), ("BTC/TUSD", "15m")]
return informative_pairs
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# dataframe['profit'] = 0
# RSI
dataframe['rsi'] = ta.RSI(dataframe)
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_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_5'] = dataframe['normal'].rolling(5).var()
dataframe['normal_var_10'] = dataframe['normal'].rolling(10).var()
dataframe['normal_var_20'] = dataframe['normal'].rolling(20).var()
dataframe['normal_var_50'] = dataframe['normal'].rolling(50).var()
# 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['cmf20'] = cmf(dataframe, 20)
dataframe['cmf50'] = cmf(dataframe, 50)
dataframe['cmf100'] = cmf(dataframe, 100)
# 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=self.inf_tf)
# Get the 14 day rsi
informative['rsi'] = ta.RSI(informative, timeperiod=14)
# informative["percent"] = (informative["close"] - informative["open"]) / informative["open"]
# informative["percent5"] = informative["percent"].rolling(5).sum()
# informative["percent3"] = informative["percent"].rolling(3).sum()
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])
pandas.set_option('display.max_rows', informative.shape[0] + 1)
pandas.set_option('display.max_columns', 50)
# print('informative', metadata['pair'], informative.tail(1))
# Use the helper function merge_informative_pair to safely merge the pair
# Automatically renames the columns and merges a shorter timeframe dataframe and a longer timeframe informative pair
# use ffill to have the 1d value available in every row throughout the day.
# Without this, comparisons between columns of the original and the informative pair would only work once per day.
# Full documentation of this method, see below
dataframe = merge_informative_pair(dataframe, informative, self.timeframe, self.inf_tf, 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))
# for decalage in range(self.buy_1_decalage_deb.value, self.buy_1_decalage.value):
# if self.buy_0.value:
# conditions = list()
# condition1, dataframe = condition_generator(
# dataframe,
# buy_operator0,
# buy_indicator0,
# buy_crossed_indicator0,
# self.buy_1_real_num.value,
# self.buy_1_decalage.value
# )
# conditions.append(condition1)
# dataframe.loc[
# (
# reduce(lambda x, y: x & y, conditions)
# & (dataframe['cmf100'] < self.buy_1_cmf100_sup.value)
# & (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= self.buy_1_volume.value)
# & (dataframe['sma10'].shift(1) <= dataframe['sma10'])
# & (dataframe['close'] < dataframe['bb_middleband'])
# & (dataframe['open'] < dataframe['sma10'])
# & (dataframe['open'] < dataframe['sma100'])
# & (dataframe['min50'].shift(decalage) == dataframe['min50'])
# & (dataframe['open'] <= dataframe['min200'] * self.buy_1_min.value)
# & (dataframe['percent20'].shift(decalage) <= self.buy_0_percent20.value)
# # & (dataframe['min20'] == dataframe['min50'])
# & (dataframe['distance_min'] <= self.buy_1_distance.value)
# & (dataframe['normal_var_20'] >= self.buy_1_normal_var.value)
# ), ['buy', 'buy_tag']] = (1, 'buy_1_' + str(decalage))
# for decalage in range(self.buy_2_decalage_deb.value, self.buy_2_decalage.value):
# if self.buy_2.value:
# dataframe.loc[
# (
# (dataframe['cond1'].shift(decalage) <= self.buy_2_cond_num.value)
# & (dataframe['cond1'].shift(decalage) >= self.buy_3_cond_num.value)
# & (dataframe['cond1_1h'] <= self.buy_2_cond_1h_num.value)
# & (dataframe['cmf100'] >= self.buy_2_cmf100_sup.value)
# & (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= self.buy_2_volume.value)
# # & (dataframe['sma10'].shift(1) <= dataframe['sma10'])
# & (dataframe['close'] < dataframe['sma10'])
# & (dataframe['open'] < dataframe['sma100'])
# & (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['normal_var_20'] >= self.buy_2_normal_var.value)
# ), ['buy', 'buy_tag']] = (1, 'buy_2_' + str(decalage))
for decalage in range(self.buy_3_decalage_deb.value, self.buy_3_decalage.value):
if self.buy_3.value:
dataframe.loc[
(
(dataframe['cond1'].shift(decalage) <= self.buy_3_cond_num.value)
& (dataframe['cond1_1h'] <= self.buy_3_cond_1h_num.value)
& (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= self.buy_3_volume.value)
# & (dataframe['sma10'].shift(1) <= dataframe['sma10'])
& (dataframe['cmf100'] < self.buy_3_cmf100_sup.value)
& (dataframe['cmf100'] > self.buy_3_cmf100_inf.value)
# & (dataframe['cmf100'] > self.buy_3_cmf100_inf.value)
& (dataframe['close'] < dataframe['sma10'])
& (dataframe['open'] < dataframe['sma100'])
& (dataframe['open'] < dataframe['sma10'])
& (dataframe['min50'].shift(decalage) == dataframe['min50'])
# & (dataframe['open'] <= dataframe['min200'] * self.buy_3_min.value)
& (dataframe['percent20'].shift(decalage) <= self.buy_3_percent20.value)
& (dataframe['distance_min'] <= self.buy_3_distance.value)
# & (dataframe['normal_var_20'] >= self.buy_3_normal_var.value)
), ['buy', 'buy_tag']] = (1, 'buy_3_' + str(decalage))
# 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

52
GodStraJD3_7_5_9.json Normal file
View File

@@ -0,0 +1,52 @@
{
"strategy_name": "GodStraJD3_7_5_9",
"params": {
"roi": {
"0": 10
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.026,
"trailing_stop_positive_offset": 0.077,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_0_distance": -0.08,
"buy_0_percent20": 0.01,
"buy_1_bb_lower_5": 0.06,
"buy_2_bb_lower_5": 0.59,
"buy_2_distance": 0.1,
"buy_2_percent20": 0.05,
"buy_3_bb_lower_5": 0.47,
"buy_3_distance": 0.05,
"buy_3_percent20": -0.07,
"buy_decalage0": 7,
"buy_decalage2": 6,
"buy_decalage3": 8,
"buy_decalage_deb_0": 1,
"buy_decalage_deb_2": 1,
"buy_decalage_deb_3": 2,
"buy_min_horizon": 119,
"buy_real_num0": 0.14,
"buy_real_num1": 0.36,
"buy_real_num2": 1.71
},
"sell": {
"sell_candels": 40,
"sell_percent": 0.0,
"sell_percent3": 0.014
},
"protection": {
"lookback": 133,
"protection_max_allowed_dd": 0.71,
"protection_stop": 61,
"protection_stoploss_stop": 50,
"trade_limit": 9
}
},
"ft_stratparam_v": 1,
"export_time": "2022-03-25 00:29:29.617986+00:00"
}

861
GodStraJD3_7_5_9.py Normal file
View File

@@ -0,0 +1,861 @@
# 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 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
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_9(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'},
'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 = False
profit_old_sma10 = False
profit_over_rsi = True
profit_quick_gain = True
profit_quick_gain_3 = True
profit_quick_lost = True
profit_short_loss = False
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_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_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')
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
}
]
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 >= -0.01) & ((current_time - trade.open_date_utc).days >= 5)\
& ((current_time - trade.open_date_utc).days < 10)\
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
return "too_old_0.01"
if (current_profit >= -0.02) & ((current_time - trade.open_date_utc).days >= 10)\
& ((current_time - trade.open_date_utc).days < 15) \
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
return "too_old_0.02"
if (current_profit >= -0.03) & ((current_time - trade.open_date_utc).days >= 15) \
& (previous_last_candle['sma10'] > last_candle['sma10']) & (last_candle['percent3'] < 0):
return "too_old_0.03"
if self.profit_quick_lost:
if (current_profit >= 0.015) & (last_candle['percent3'] < -0.005):
return "quick_lost"
if self.profit_no_change:
if (current_profit > 0.005) & (last_candle['percent10'] < 0.001) & (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 > 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_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'] > 88): # & (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'] > 82) & (last_candle['percent'] < -0.02): #| (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, "4h") 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 += [("ETH/USDT", "5m"), ("BTC/TUSD", "15m")]
#
# return informative_pairs
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# dataframe['profit'] = 0
# RSI
dataframe['rsi'] = ta.RSI(dataframe)
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="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))
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['percent_1d'] >= self.buy_1_percent_1d_num.value)
#& (dataframe['percent_4h'] > 0)
#& (dataframe['percent3_4h'] <= self.buy_1_percent_4h_num.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['percent_4h'] > 0)
#& (dataframe['percent3_4h'] <= self.buy_2_percent_4h_num.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['percent_4h'] > 0)
#& (dataframe['percent3_4h'] <= self.buy_3_percent_4h_num.value)
), ['buy', 'buy_tag']] = (1, 'buy_3_' + 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

67
GodStraJD3_7_5_9_1.json Normal file
View File

@@ -0,0 +1,67 @@
{
"strategy_name": "GodStraJD3_7_5_9_1",
"params": {
"roi": {
"0": 10
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.026,
"trailing_stop_positive_offset": 0.077,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_0_distance": -0.03,
"buy_0_percent20": -0.03,
"buy_1_bb_lower_5": 0.19,
"buy_1_pente_sma10": 0.48,
"buy_1_pente_sma20": 0.33,
"buy_2_bb_lower_5": 0.59,
"buy_2_distance": 0.08,
"buy_2_pente_sma10": 0.46,
"buy_2_pente_sma20": 0.08,
"buy_2_percent20": 0.06,
"buy_3_bb_lower_5": 0.05,
"buy_3_distance": 0.01,
"buy_3_pente_sma10": 0.12,
"buy_3_pente_sma20": 0.27,
"buy_3_percent20": -0.03,
"buy_4_pente_sma10": 0.35,
"buy_4_pente_sma20": 0.22,
"buy_decalage0": 7,
"buy_decalage2": 6,
"buy_decalage3": 7,
"buy_decalage_deb_0": 1,
"buy_decalage_deb_2": 1,
"buy_decalage_deb_3": 1,
"buy_min_horizon": 192,
"buy_real_num0": 0.61,
"buy_real_num1": 0.34,
"buy_real_num2": 0.35
},
"sell": {
"sell_RSI": 95,
"sell_RSI2": 81,
"sell_RSI2_percent": 0.008,
"sell_candels": 17,
"sell_percent": 0.016,
"sell_percent3": 0.001,
"sell_profit_no_change": 0.016,
"sell_profit_percent10": 0.0002,
"sell_too_old_day": 7,
"sell_too_old_percent": 0.005
},
"protection": {
"lookback": 133,
"protection_max_allowed_dd": 0.71,
"protection_stop": 61,
"protection_stoploss_stop": 50,
"trade_limit": 9
}
},
"ft_stratparam_v": 1,
"export_time": "2022-03-29 20:57:57.922162+00:00"
}

863
GodStraJD3_7_5_9_1.py Normal file
View File

@@ -0,0 +1,863 @@
# 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_9_1(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'},
'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_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_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 (current_profit > 0.015) & (last_candle['percent'] < -0.005):
# return 'percent_quick'
# 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 > 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, "4h") 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 += [("ETH/USDT", "5m"), ("BTC/TUSD", "15m")]
#
# 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="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))
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['bb_width'] >= 0.05)
& (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['percent_1d'] >= self.buy_1_percent_1d_num.value)
#& (dataframe['percent_4h'] > 0)
#& (dataframe['percent3_4h'] <= self.buy_1_percent_4h_num.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['bb_width'] >= 0.05)
& (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['percent_4h'] > 0)
#& (dataframe['percent3_4h'] <= self.buy_2_percent_4h_num.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['bb_width'] >= 0.05)
& (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['percent_4h'] > 0)
#& (dataframe['percent3_4h'] <= self.buy_3_percent_4h_num.value)
), ['buy', 'buy_tag']] = (1, 'buy_3_' + str(decalage))
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
return dataframe

97
GodStraJD3_7_5_9_2.json Normal file
View File

@@ -0,0 +1,97 @@
{
"strategy_name": "GodStraJD3_7_5_9_2",
"params": {
"roi": {
"0": 10
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.026,
"trailing_stop_positive_offset": 0.077,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_0_distance": -0.05,
"buy_0_percent20": 0.04,
"buy_1_bb_lower_5": 0.36,
"buy_1_pente_sma10": 0.22,
"buy_1_pente_sma20": 0.6,
"buy_2_bb_lower_5": 0.23,
"buy_2_distance": 0.09,
"buy_2_pente_sma10": 0.36,
"buy_2_pente_sma20": 0.46,
"buy_2_percent20": 0.02,
"buy_3_bb_lower_5": 0.48,
"buy_3_distance": 0.01,
"buy_3_pente_sma10": 0.53,
"buy_3_pente_sma20": 0.11,
"buy_3_percent20": -0.09,
"buy_4_pente_sma10": 0.48,
"buy_4_pente_sma20": 0.38,
"buy_bb_lowerband": 1.02,
"buy_bb_width": 0.08,
"buy_cat": "<R",
"buy_decalage0": 6,
"buy_decalage2": 6,
"buy_decalage3": 8,
"buy_decalage_deb_0": 3,
"buy_decalage_deb_2": 0,
"buy_decalage_deb_3": 2,
"buy_min_horizon": 179,
"buy_pct": 0.001,
"buy_pct_1": 0.0,
"buy_pct_3": 0.0,
"buy_pct_5": 0.0,
"buy_real": 0.3488,
"buy_real_num0": 0.88,
"buy_real_num1": 0.25,
"buy_real_num2": 0.59
},
"sell": {
"profit_h_no_change": false,
"profit_h_old_sma10": false,
"profit_h_over_rsi": true,
"profit_h_quick_gain": true,
"profit_h_quick_gain_3": true,
"profit_h_quick_lost": false,
"profit_h_short_loss": true,
"profit_h_sma10": false,
"profit_h_sma20": true,
"profit_h_sma5": false,
"profit_h_very_old_sma10": false,
"profit_no_change": true,
"profit_old_sma10": true,
"profit_over_rsi": false,
"profit_quick_gain": false,
"profit_quick_gain_3": false,
"profit_quick_lost": false,
"profit_short_loss": false,
"profit_sma10": true,
"profit_sma20": false,
"profit_sma5": true,
"profit_very_old_sma10": true,
"sell_RSI": 96,
"sell_RSI2": 93,
"sell_RSI2_percent": 0.005,
"sell_candels": 10,
"sell_percent": 0.008,
"sell_percent3": 0.013,
"sell_profit_no_change": 0.009,
"sell_profit_percent10": 0.0016,
"sell_too_old_day": 10,
"sell_too_old_percent": 0.001
},
"protection": {
"lookback": 133,
"protection_max_allowed_dd": 0.71,
"protection_stop": 61,
"protection_stoploss_stop": 50,
"trade_limit": 9
}
},
"ft_stratparam_v": 1,
"export_time": "2022-04-02 11:22:43.739711+00:00"
}

811
GodStraJD3_7_5_9_2.py Normal file
View File

@@ -0,0 +1,811 @@
# 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 ta as ta2
import calendar
from freqtrade.loggers import setup_logging
from freqtrade.strategy.strategy_helper import merge_informative_pair
# --------------------------------
# Add your lib to import here
# TODO: ta 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_9_2(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'},
'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 ####################
trades = list()
profit_no_change = BooleanParameter(default=True, space="sell")
profit_quick_lost = BooleanParameter(default=True, space="sell")
profit_sma5 = BooleanParameter(default=True, space="sell")
profit_sma10 = BooleanParameter(default=True, space="sell")
profit_sma20 = BooleanParameter(default=True, space="sell")
profit_quick_gain = BooleanParameter(default=True, space="sell")
profit_quick_gain_3 = BooleanParameter(default=True, space="sell")
profit_old_sma10 = BooleanParameter(default=True, space="sell")
profit_very_old_sma10 = BooleanParameter(default=True, space="sell")
profit_over_rsi = BooleanParameter(default=True, space="sell")
profit_short_loss = BooleanParameter(default=True, 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")
# buy_signal_bb_width = DecimalParameter(0.06, 0.15, decimals=2, default=0.065, space='buy')
buy_real = DecimalParameter(0.001, 0.999, decimals=4, default=0.11908, space='buy')
buy_cat = CategoricalParameter([">R", "=R", "<R"], default='<R', space='buy')
buy_pct = DecimalParameter(0.001, 0.02, decimals=3, default=0.005, space='buy')
buy_pct_1 = DecimalParameter(-0.2, 0.2, decimals=2, default=0.005, space='buy')
buy_pct_3 = DecimalParameter(-0.2, 0.2, decimals=2, default=0.005, space='buy')
buy_pct_5 = DecimalParameter(-0.2, 0.2, decimals=2, default=0.005, space='buy')
buy_bb_lowerband = DecimalParameter(1, 1.05, default=1, decimals=2, space='buy')
buy_bb_width = DecimalParameter(0.01, 0.15, default=0.065, decimals=2, 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_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_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_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')
@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()
expected_profit = 0.01
# if (last_candle['pct_change_1_1d'] < 0):
# expected_profit = self.sell_expected_profit.value
#
# if (current_profit > expected_profit) & (last_candle['pct_change_1_1d'] < 0):
# return "exp_profit_down"
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 (last_candle['pct_change_1_1d'] > 0):
if self.profit_quick_lost.value and (current_profit >= 0.015) & (last_candle['percent3'] < -0.005):
return "quick_lost"
if self.profit_no_change.value 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 > 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.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 'sma5'
if self.profit_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 'sma10'
if self.profit_sma20.value:
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_over_rsi.value:
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.value:
if (current_profit > -expected_profit) & (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'
else:
if self.profit_h_quick_lost.value and (current_profit >= 0.015) & (last_candle['percent3'] < -0.005):
return "h_quick_lost"
if self.profit_h_no_change.value 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 "h_no_change"
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 "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 > 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 'h_sma20'
if self.profit_h_over_rsi.value:
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 'h_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 'h_over_rsi_2'
if self.profit_h_short_loss.value:
if (current_profit > -expected_profit) & (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 'h_short_lost'
def informative_pairs(self):
pairs = self.dp.current_whitelist()
informative_pairs = [(pair, '1d') for pair in pairs]
return informative_pairs
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# dataframe['profit'] = 0
# RSI
dataframe['trend_ichimoku_base'] = ta2.trend.ichimoku_base_line(
dataframe['high'],
dataframe['low'],
window1=9,
window2=26,
visual=False,
fillna=False
)
KST = ta2.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['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['max50'] = ta.MAX(dataframe['close'], timeperiod=50)
dataframe['max200'] = ta.MAX(dataframe['close'], timeperiod=200)
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()
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[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])
# 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())
informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe="1d")
informative["rsi"] = ta.RSI(informative)
informative["max3"] = ta.MAX(informative['close'], timeperiod=3)
informative["min3"] = ta.MIN(informative['close'], timeperiod=3)
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'] = ta.SMA(informative, timeperiod=3)
informative['sma5'] = ta.SMA(informative, timeperiod=5)
informative['sma10'] = ta.SMA(informative, timeperiod=10)
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)
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
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['percent_1d'] >= self.buy_1_percent_1d_num.value)
#& (dataframe['percent_4h'] > 0)
#& (dataframe['percent3_4h'] <= self.buy_1_percent_4h_num.value)
& (dataframe['pct_change_1_1d'] < self.buy_pct_1.value)
& (dataframe['pct_change_3_1d'] < self.buy_pct_3.value)
& (dataframe['pct_change_5_1d'] < self.buy_pct_5.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['percent_4h'] > 0)
#& (dataframe['percent3_4h'] <= self.buy_2_percent_4h_num.value)
& (dataframe['pct_change_1_1d'] < self.buy_pct_1.value)
& (dataframe['pct_change_3_1d'] < self.buy_pct_3.value)
& (dataframe['pct_change_5_1d'] < self.buy_pct_5.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['percent_4h'] > 0)
#& (dataframe['percent3_4h'] <= self.buy_3_percent_4h_num.value)
& (dataframe['pct_change_1_1d'] < self.buy_pct_1.value)
& (dataframe['pct_change_3_1d'] < self.buy_pct_3.value)
& (dataframe['pct_change_5_1d'] < self.buy_pct_5.value)
), ['buy', 'buy_tag']] = (1, 'buy_3_' + str(decalage))
conditions = []
IND = 'trend_ichimoku_base'
REAL = self.buy_real.value
OPR = self.buy_cat.value
DFIND = dataframe[IND]
# print(DFIND.mean())
if OPR == ">R":
conditions.append(DFIND > REAL)
elif OPR == "=R":
conditions.append(np.isclose(DFIND, REAL))
elif OPR == "<R":
conditions.append(DFIND < REAL)
if conditions:
dataframe.loc[
(reduce(lambda x, y: x & y, conditions))
& (dataframe['pct_change'] < - self.buy_pct.value)
& (dataframe['close'] <= dataframe['min200'] * 1.002)
& (dataframe['pct_change_1_1d'] > self.buy_pct_1.value)
& (dataframe['pct_change_3_1d'] > self.buy_pct_3.value)
& (dataframe['pct_change_5_1d'] > self.buy_pct_5.value)
#& (dataframe['close_1d'] < dataframe['bb_lowerband_1d'] * self.buy_bb_lowerband.value)
& (dataframe['bb_width_1d'] >= self.buy_bb_width.value)
& (dataframe['close'] <= dataframe['sma5_1d'])
& (dataframe['sma10_1d'].shift(1) <= dataframe['sma10_1d'])
,
'buy'] = 1
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
return dataframe

63
GodStraJD3_7_6.json Normal file
View File

@@ -0,0 +1,63 @@
{
"strategy_name": "GodStraJD3_7_6",
"params": {
"roi": {
"0": 10
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.026,
"trailing_stop_positive_offset": 0.077,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_1_distance": 0.06,
"buy_1_percent20": -0.04,
"buy_3_distance": 0.01,
"buy_3_percent20": 0.08,
"buy_decalage1": 8,
"buy_decalage3": 7,
"buy_decalage_deb_1": 2,
"buy_decalage_deb_3": 3,
"buy_min_horizon": 111,
"buy_real_num1": 0.77,
"buy_real_num3": 0.52
},
"sell": {
"profit_no_change": false,
"profit_old_sma10": true,
"profit_over_rsi": false,
"profit_over_rsi2_percent": 0.002,
"profit_over_rsi_max_rsi": 90,
"profit_over_rsi_max_rsi2": 94,
"profit_quick_gain": false,
"profit_quick_gain_3": false,
"profit_quick_lost": true,
"profit_quick_lost_max": 0.0,
"profit_quick_lost_max_profit": 0.013,
"profit_short_loss": true,
"profit_sma10": true,
"profit_sma10_current_profit": 0.027,
"profit_sma10_facteur": 1.0,
"profit_sma20": true,
"profit_sma20_current_profit": 0.021,
"profit_sma20_facteur": 1.006,
"profit_too_old": true,
"profit_too_old_days": 9,
"profit_too_old_max": 0.02,
"profit_very_old_sma10": false
},
"protection": {
"lookback": 133,
"protection_max_allowed_dd": 0.71,
"protection_stop": 61,
"protection_stoploss_stop": 50,
"trade_limit": 9
}
},
"ft_stratparam_v": 1,
"export_time": "2022-03-12 10:23:55.007196+00:00"
}

787
GodStraJD3_7_6.py Normal file
View File

@@ -0,0 +1,787 @@
# 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 calendar
from freqtrade.loggers import setup_logging
# --------------------------------
# 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
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_6(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'},
'sma10': {'color': 'yellow'},
'min20': {'color': '#87e470'},
'min50': {'color': '#ac3e2a'},
"min1.1": {'color': 'yellow'},
'sma20': {'color': 'cyan'}
},
'subplots': {
# Subplots - each dict defines one additional plot
"BB": {
'bb_width': {'color': 'white'}
},
# "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": {
'ecart_20': {'color': 'red'},
'ecart_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 = False
# profit_old_sma10 = False
# profit_over_rsi = True
# profit_quick_gain = True
# profit_quick_gain_3 = True
# profit_quick_lost = False
# profit_short_loss = False
# profit_sma10 = False
# profit_sma20 = True
# profit_very_old_sma10 = False
trades = list()
profit_too_old = BooleanParameter(default=True, space="sell")
profit_no_change = BooleanParameter(default=True, space="sell")
profit_quick_lost = BooleanParameter(default=True, space="sell")
profit_sma10 = BooleanParameter(default=True, space="sell")
profit_sma20 = BooleanParameter(default=True, space="sell")
profit_quick_gain = BooleanParameter(default=True, space="sell")
profit_quick_gain_3 = BooleanParameter(default=True, space="sell")
profit_old_sma10 = BooleanParameter(default=True, space="sell")
profit_very_old_sma10 = BooleanParameter(default=True, space="sell")
profit_over_rsi = BooleanParameter(default=True, space="sell")
profit_short_loss = BooleanParameter(default=True, space="sell")
profit_too_old_max = DecimalParameter(0, 0.05, decimals=2, default=0.01, space='sell')
profit_too_old_days = IntParameter(1, 10, default=5, space='sell')
profit_quick_lost_max = DecimalParameter(0, 0.03, decimals=3, default=0.015, space='sell')
profit_quick_lost_max_profit = DecimalParameter(0, 0.03, decimals=3, default=0.015, space='sell')
profit_sma10_current_profit = DecimalParameter(0, 0.03, decimals=3, default=0.015, space='sell')
profit_sma10_facteur = DecimalParameter(1, 1.01, decimals=3, default=1.005, space='sell')
profit_sma20_current_profit = DecimalParameter(0, 0.03, decimals=3, default=0.015, space='sell')
profit_sma20_facteur = DecimalParameter(1, 1.01, decimals=3, default=1.005, space='sell')
profit_over_rsi_max_rsi = IntParameter(70, 100, default=88, space='sell')
profit_over_rsi_max_rsi2 = IntParameter(70, 100, default=82, space='sell')
profit_over_rsi2_percent = DecimalParameter(0, 0.05, decimals=3, default=0.02, space='sell')
# 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_num3 = DecimalParameter(0, 2, 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_1_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_1_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(1, 3, default=5, space='buy')
buy_decalage_deb_1 = IntParameter(1, 3, default=5, space='buy')
buy_decalage_deb_3 = IntParameter(1, 3, default=5, space='buy')
# buy_decalage0 = IntParameter(buy_decalage_deb_0.value + 1, 8, default=5, space='buy')
buy_decalage1 = IntParameter(buy_decalage_deb_1.value + 1, 8, default=5, space='buy')
buy_decalage3 = IntParameter(buy_decalage_deb_3.value + 1, 8, default=5, 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')
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
}
]
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 self.profit_too_old.value:
if (current_profit >= - self.profit_too_old_max.value) \
& ((current_time - trade.open_date_utc).days >= self.profit_too_old_days.value)\
& ((current_time - trade.open_date_utc).days < (self.profit_too_old_days.value * 2))\
& (previous_last_candle['sma20'] > last_candle['sma20']):
return "too_old_0.01"
if (current_profit >= - (2 * self.profit_too_old_max.value)) \
& ((current_time - trade.open_date_utc).days >= (self.profit_too_old_days.value * 2))\
& ((current_time - trade.open_date_utc).days < (self.profit_too_old_days.value * 3)) \
& (previous_last_candle['sma20'] > last_candle['sma20']):
return "too_old_0.02"
if (current_profit >= - (3 * self.profit_too_old_max.value)) \
& ((current_time - trade.open_date_utc).days >= (self.profit_too_old_days.value * 3)) \
& (previous_last_candle['sma20'] > last_candle['sma20']):
return "too_old_0.03"
if self.profit_quick_lost.value:
if (current_profit >= self.profit_quick_lost_max_profit.value) \
& (last_candle['percent3'] < - self.profit_quick_lost_max.value):
return "quick_lost"
if self.profit_no_change.value:
if (current_profit > 0.005) \
& (last_candle['percent10'] < 0.000) \
& (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.value:
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.value:
if (0.01 < current_profit < 0.03) \
& (last_candle['percent'] < 0) \
& ((current_time - trade.open_date_utc).seconds <= 3600):
return "quick_gain"
if self.profit_sma10.value:
if (current_profit > self.profit_sma10_current_profit.value) \
& ((previous_5_candle['sma10'] > (last_candle['sma10'] * self.profit_sma10_facteur.value)) \
| (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.value:
if (current_profit > self.profit_sma20_current_profit.value) & (last_candle['percent5'] < 0) \
& (previous_5_candle['sma10'] > last_candle['sma10']) \
& ((current_time - trade.open_date_utc).seconds >= 3600) \
& ((previous_last_candle['sma20'] > (last_candle['sma20'] * self.profit_sma20_facteur.value)) &
((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.value:
if (current_profit > 0) & (last_candle['rsi'] > self.profit_over_rsi_max_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.profit_over_rsi_max_rsi2.value) \
& (last_candle['percent'] < - self.profit_over_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.value:
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):
return []
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# dataframe['profit'] = 0
# RSI
dataframe['rsi'] = ta.RSI(dataframe)
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["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_min'] = ta.MIN(dataframe['bb_lowerband'], timeperiod=36)
dataframe['distance_min'] = (dataframe['close'] - dataframe['min']) / dataframe['close']
dataframe['min1.1'] = 1.01 * dataframe['min']
# 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)
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))
# 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['sma100'])
# & (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)
# ), ['buy', 'buy_tag']] = (1, 'buy_1_' + str(decalage))
for decalage in range(self.buy_decalage_deb_1.value, self.buy_decalage1.value):
dataframe.loc[
(
(dataframe['cond1'].shift(decalage) <= self.buy_real_num1.value)
& (dataframe['bb_width'].shift(decalage) >= 0.07)
& (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= 10)
# & (dataframe['close'] < dataframe['sma10'])
& (dataframe['sma50'].shift(decalage) < dataframe['sma50'])
#& (dataframe['open'] < dataframe['min1.1'])
# & (dataframe['open'] < dataframe['sma10'])
& (dataframe['min50'].shift(decalage) == dataframe['min50'])
#& (dataframe['min10'] <= dataframe['min50'] * 1.02)
& (dataframe['percent20'].shift(decalage) <= self.buy_1_percent20.value)
# & (dataframe['min20'] == dataframe['min50'])
& (dataframe['distance_min'] <= self.buy_1_distance.value)
), ['buy', 'buy_tag']] = (1, 'buy_1_' + 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) <= self.buy_real_num3.value)
& (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= 10)
# & (dataframe['sma10'].shift(1) <= dataframe['sma10'])
& (dataframe['close'] < dataframe['sma10'])
& (dataframe['open'] < dataframe['sma100'])
& (dataframe['open'] < dataframe['sma10'])
#& (dataframe['open'] < dataframe['min1.1'])
& (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)
), ['buy', 'buy_tag']] = (1, 'buy_3_' + str(decalage))
# 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

63
GodStraJD3_7_6_2.json Normal file
View File

@@ -0,0 +1,63 @@
{
"strategy_name": "GodStraJD3_7_6_2",
"params": {
"roi": {
"0": 10
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.026,
"trailing_stop_positive_offset": 0.077,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_1_distance": -0.02,
"buy_1_percent20": 0.03,
"buy_3_distance": 0.05,
"buy_3_percent20": 0.01,
"buy_decalage1": 8,
"buy_decalage3": 8,
"buy_decalage_deb_1": 2,
"buy_decalage_deb_3": 1,
"buy_min_horizon": 195,
"buy_real_num1": 0.55,
"buy_real_num3": 0.55
},
"sell": {
"profit_no_change": false,
"profit_old_sma10": true,
"profit_over_rsi": false,
"profit_over_rsi2_percent": 0.002,
"profit_over_rsi_max_rsi": 90,
"profit_over_rsi_max_rsi2": 94,
"profit_quick_gain": false,
"profit_quick_gain_3": false,
"profit_quick_lost": true,
"profit_quick_lost_max": 0.0,
"profit_quick_lost_max_profit": 0.013,
"profit_short_loss": true,
"profit_sma10": true,
"profit_sma10_current_profit": 0.027,
"profit_sma10_facteur": 1.0,
"profit_sma20": true,
"profit_sma20_current_profit": 0.021,
"profit_sma20_facteur": 1.006,
"profit_too_old": true,
"profit_too_old_days": 9,
"profit_too_old_max": 0.02,
"profit_very_old_sma10": false
},
"protection": {
"lookback": 133,
"protection_max_allowed_dd": 0.71,
"protection_stop": 61,
"protection_stoploss_stop": 50,
"trade_limit": 9
}
},
"ft_stratparam_v": 1,
"export_time": "2022-03-12 00:18:04.975397+00:00"
}

788
GodStraJD3_7_6_2.py Normal file
View File

@@ -0,0 +1,788 @@
# 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 calendar
from freqtrade.loggers import setup_logging
# --------------------------------
# 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
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_6_2(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'},
'sma10': {'color': 'yellow'},
'min20': {'color': '#87e470'},
'min50': {'color': '#ac3e2a'},
"min1.1": {'color': 'yellow'},
'sma20': {'color': 'cyan'}
},
'subplots': {
# Subplots - each dict defines one additional plot
"BB": {
'bb_width': {'color': 'white'}
},
# "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": {
'ecart_20': {'color': 'red'},
'ecart_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 = False
# profit_old_sma10 = False
# profit_over_rsi = True
# profit_quick_gain = True
# profit_quick_gain_3 = True
# profit_quick_lost = False
# profit_short_loss = False
# profit_sma10 = False
# profit_sma20 = True
# profit_very_old_sma10 = False
trades = list()
profit_too_old = BooleanParameter(default=True, space="sell")
profit_no_change = BooleanParameter(default=True, space="sell")
profit_quick_lost = BooleanParameter(default=True, space="sell")
profit_sma10 = BooleanParameter(default=True, space="sell")
profit_sma20 = BooleanParameter(default=True, space="sell")
profit_quick_gain = BooleanParameter(default=True, space="sell")
profit_quick_gain_3 = BooleanParameter(default=True, space="sell")
profit_old_sma10 = BooleanParameter(default=True, space="sell")
profit_very_old_sma10 = BooleanParameter(default=True, space="sell")
profit_over_rsi = BooleanParameter(default=True, space="sell")
profit_short_loss = BooleanParameter(default=True, space="sell")
profit_too_old_max = DecimalParameter(0, 0.05, decimals=2, default=0.01, space='sell')
profit_too_old_days = IntParameter(1, 10, default=5, space='sell')
profit_quick_lost_max = DecimalParameter(0, 0.03, decimals=3, default=0.015, space='sell')
profit_quick_lost_max_profit = DecimalParameter(0, 0.03, decimals=3, default=0.015, space='sell')
profit_sma10_current_profit = DecimalParameter(0, 0.03, decimals=3, default=0.015, space='sell')
profit_sma10_facteur = DecimalParameter(1, 1.01, decimals=3, default=1.005, space='sell')
profit_sma20_current_profit = DecimalParameter(0, 0.03, decimals=3, default=0.015, space='sell')
profit_sma20_facteur = DecimalParameter(1, 1.01, decimals=3, default=1.005, space='sell')
profit_over_rsi_max_rsi = IntParameter(70, 100, default=88, space='sell')
profit_over_rsi_max_rsi2 = IntParameter(70, 100, default=82, space='sell')
profit_over_rsi2_percent = DecimalParameter(0, 0.05, decimals=3, default=0.02, space='sell')
# 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_num3 = DecimalParameter(0, 2, 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_1_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_1_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(1, 3, default=5, space='buy')
buy_decalage_deb_1 = IntParameter(1, 3, default=5, space='buy')
buy_decalage_deb_3 = IntParameter(1, 3, default=5, space='buy')
# buy_decalage0 = IntParameter(buy_decalage_deb_0.value + 1, 8, default=5, space='buy')
buy_decalage1 = IntParameter(buy_decalage_deb_1.value + 1, 8, default=5, space='buy')
buy_decalage3 = IntParameter(buy_decalage_deb_3.value + 1, 8, default=5, 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')
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
}
]
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 self.profit_too_old.value:
if (current_profit >= - self.profit_too_old_max.value) \
& ((current_time - trade.open_date_utc).days >= self.profit_too_old_days.value)\
& ((current_time - trade.open_date_utc).days < (self.profit_too_old_days.value * 2))\
& (previous_last_candle['sma20'] > last_candle['sma20']):
return "too_old_0.01"
if (current_profit >= - (2 * self.profit_too_old_max.value)) \
& ((current_time - trade.open_date_utc).days >= (self.profit_too_old_days.value * 2))\
& ((current_time - trade.open_date_utc).days < (self.profit_too_old_days.value * 3)) \
& (previous_last_candle['sma20'] > last_candle['sma20']):
return "too_old_0.02"
if (current_profit >= - (3 * self.profit_too_old_max.value)) \
& ((current_time - trade.open_date_utc).days >= (self.profit_too_old_days.value * 3)) \
& (previous_last_candle['sma20'] > last_candle['sma20']):
return "too_old_0.03"
if self.profit_quick_lost.value:
if (current_profit >= self.profit_quick_lost_max_profit.value) \
& (last_candle['percent3'] < - self.profit_quick_lost_max.value):
return "quick_lost"
if self.profit_no_change.value:
if (current_profit > 0.005) \
& (last_candle['percent10'] < 0.000) \
& (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.value:
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.value:
if (0.01 < current_profit < 0.03) \
& (last_candle['percent'] < 0) \
& ((current_time - trade.open_date_utc).seconds <= 3600):
return "quick_gain"
if self.profit_sma10.value:
if (current_profit > self.profit_sma10_current_profit.value) \
& ((previous_5_candle['sma10'] > (last_candle['sma10'] * self.profit_sma10_facteur.value)) \
| (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.value:
if (current_profit > self.profit_sma20_current_profit.value) & (last_candle['percent5'] < 0) \
& (previous_5_candle['sma10'] > last_candle['sma10']) \
& ((current_time - trade.open_date_utc).seconds >= 3600) \
& ((previous_last_candle['sma20'] > (last_candle['sma20'] * self.profit_sma20_facteur.value)) &
((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.value:
if (current_profit > 0) & (last_candle['rsi'] > self.profit_over_rsi_max_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.profit_over_rsi_max_rsi2.value) \
& (last_candle['percent'] < - self.profit_over_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.value:
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):
return []
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# dataframe['profit'] = 0
# RSI
dataframe['rsi'] = ta.RSI(dataframe)
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["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_min'] = ta.MIN(dataframe['bb_lowerband'], timeperiod=36)
dataframe['distance_min'] = (dataframe['close'] - dataframe['min']) / dataframe['close']
dataframe['min1.1'] = 1.01 * dataframe['min']
# 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)
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))
# 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['sma100'])
# & (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)
# ), ['buy', 'buy_tag']] = (1, 'buy_1_' + str(decalage))
for decalage in range(self.buy_decalage_deb_1.value, self.buy_decalage1.value):
dataframe.loc[
(
(dataframe['cond1'].shift(decalage) <= self.buy_real_num1.value)
& (dataframe['bb_width'].shift(decalage) >= 0.07)
# & (dataframe['close'].shift(decalage) < dataframe['bb_lowerband'].shift(decalage))
& (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= 10)
& (dataframe['close'] < dataframe['sma10'])
& (dataframe['sma50'].shift(decalage) < dataframe['sma50'])
#& (dataframe['open'] < dataframe['min1.1'])
# & (dataframe['open'] < dataframe['sma10'])
& (dataframe['min50'].shift(decalage) == dataframe['min50'])
#& (dataframe['min10'] <= dataframe['min50'] * 1.02)
& (dataframe['percent20'].shift(decalage) <= self.buy_1_percent20.value)
# & (dataframe['min20'] == dataframe['min50'])
& (dataframe['distance_min'] <= self.buy_1_distance.value)
), ['buy', 'buy_tag']] = (1, 'buy_1_' + 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) <= self.buy_real_num3.value)
& (dataframe['volume10'].shift(decalage) * dataframe['close'].shift(decalage) / 1000 >= 10)
& (dataframe['sma10'].shift(1) <= dataframe['sma10'])
& (dataframe['close'] < dataframe['sma10'])
& (dataframe['open'] < dataframe['sma100'])
& (dataframe['open'] < dataframe['sma10'])
#& (dataframe['open'] < dataframe['min1.1'])
& (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)
), ['buy', 'buy_tag']] = (1, 'buy_3_' + str(decalage))
# 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

54
GodStraJD3_8.json Normal file
View File

@@ -0,0 +1,54 @@
{
"strategy_name": "GodStraJD3_8",
"params": {
"roi": {
"0": 10
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.058,
"trailing_stop_positive_offset": 0.079,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_bbwidth_num0": 0.05,
"buy_bbwidth_num1": 0.99,
"buy_cond1_num0": 1.29,
"buy_cond1_num1": 1.67,
"profit_no_change": true,
"profit_old_sma10": true,
"profit_over_rsi": true,
"profit_quick_gain": false,
"profit_quick_gain_3": false,
"profit_quick_lost": true,
"profit_short_loss": true,
"profit_sma10": true,
"profit_sma20": true,
"profit_very_old_sma10": false
},
"sell": {
"sell_crossed_indicator0": "CDLCONCEALBABYSWALL-100",
"sell_indicator0": "BBANDS-2-5",
"sell_operator0": "D",
"sell_percent": 0.01,
"sell_percent3": 0.002,
"sell_percent5": 0.025,
"sell_real_num0": 0.01
},
"protection": {
"lookback": 46,
"lookback_stoploss": 144,
"protection_cooldown": 19,
"protection_max_allowed_dd": 0.36,
"protection_stop": 79,
"protection_stoploss_stop": 13,
"trade_limit": 7,
"trade_limit_stoploss": 5
}
},
"ft_stratparam_v": 1,
"export_time": "2022-02-14 03:19:36.837525+00:00"
}

1043
GodStraJD3_8.py Normal file

File diff suppressed because it is too large Load Diff

48
GodStraJD3_9.json Normal file
View File

@@ -0,0 +1,48 @@
{
"strategy_name": "GodStraJD3_9",
"params": {
"roi": {
"0": 10
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.058,
"trailing_stop_positive_offset": 0.079,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_signal_bb_width": 1.21,
"buy_signal_condition_high": 1.02,
"buy_signal_minus": 1.22,
"buy_signal_sma10": 1.08,
"buy_signal_sma10_pente": 0.041,
"buy_signal_sma_max": 1.09,
"buy_signal_sma_min": 1.0,
"buy_signal_sma_percent50": 0.061
},
"sell": {
"sell_crossed_indicator0": "CDL3INSIDE-50",
"sell_indicator0": "CDLGAPSIDESIDEWHITE-50",
"sell_operator0": "CUT",
"sell_percent": 0.006,
"sell_percent3": 0.0,
"sell_percent5": 0.004,
"sell_real_num0": 0.13
},
"protection": {
"lookback": 46,
"lookback_stoploss": 144,
"protection_cooldown": 19,
"protection_max_allowed_dd": 0.36,
"protection_stop": 79,
"protection_stoploss_stop": 13,
"trade_limit": 7,
"trade_limit_stoploss": 5
}
},
"ft_stratparam_v": 1,
"export_time": "2022-02-17 19:22:05.539646+00:00"
}

48
GodStraJD3_9.jsonBest Normal file
View File

@@ -0,0 +1,48 @@
{
"strategy_name": "GodStraJD3_9",
"params": {
"roi": {
"0": 10
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.058,
"trailing_stop_positive_offset": 0.079,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_signal_bb_width": 1.09,
"buy_signal_condition_high": 1.1,
"buy_signal_minus": 1.09,
"buy_signal_sma10": 1.02,
"buy_signal_sma10_pente": 0.001,
"buy_signal_sma_max": 1.03,
"buy_signal_sma_min": 1.08,
"buy_signal_sma_percent50": 0.036
},
"sell": {
"sell_crossed_indicator0": "CDLSHORTLINE-50",
"sell_indicator0": "CDLSEPARATINGLINES-20",
"sell_operator0": "=R",
"sell_percent": 0.01,
"sell_percent3": 0.021,
"sell_percent5": 0.006,
"sell_real_num0": 0.84
},
"protection": {
"lookback": 46,
"lookback_stoploss": 144,
"protection_cooldown": 19,
"protection_max_allowed_dd": 0.36,
"protection_stop": 79,
"protection_stoploss_stop": 13,
"trade_limit": 7,
"trade_limit_stoploss": 5
}
},
"ft_stratparam_v": 1,
"export_time": "2022-02-17 00:06:37.000718+00:00"
}

47
GodStraJD3_9.jsonOld Normal file
View File

@@ -0,0 +1,47 @@
{
"strategy_name": "GodStraJD3_9",
"params": {
"roi": {
"0": 10
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.058,
"trailing_stop_positive_offset": 0.079,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_signal_bb_width": 1.1,
"buy_signal_condition_high": 1.07,
"buy_signal_minus": 1.07,
"buy_signal_sma": 1.08,
"buy_signal_sma10": 1.08,
"buy_signal_sma10_pente": 0.041,
"buy_signal_sma_percent50": 0.092
},
"sell": {
"sell_crossed_indicator0": "CDLSHORTLINE-50",
"sell_indicator0": "CDLSEPARATINGLINES-20",
"sell_operator0": "=R",
"sell_percent": 0.01,
"sell_percent3": 0.021,
"sell_percent5": 0.006,
"sell_real_num0": 0.84
},
"protection": {
"lookback": 46,
"lookback_stoploss": 144,
"protection_cooldown": 19,
"protection_max_allowed_dd": 0.36,
"protection_stop": 79,
"protection_stoploss_stop": 13,
"trade_limit": 7,
"trade_limit_stoploss": 5
}
},
"ft_stratparam_v": 1,
"export_time": "2022-02-16 18:51:17.244506+00:00"
}

48
GodStraJD3_9.jsonOld2 Normal file
View File

@@ -0,0 +1,48 @@
{
"strategy_name": "GodStraJD3_9",
"params": {
"roi": {
"0": 10
},
"stoploss": {
"stoploss": -1.0
},
"trailing": {
"trailing_stop": false,
"trailing_stop_positive": 0.058,
"trailing_stop_positive_offset": 0.079,
"trailing_only_offset_is_reached": true
},
"buy": {
"buy_signal_bb_width": 1.81,
"buy_signal_condition_high": 1.28,
"buy_signal_minus": 1.95,
"buy_signal_sma10": 1.02,
"buy_signal_sma10_pente": 0.055,
"buy_signal_sma_max": 1.02,
"buy_signal_sma_min": 1.03,
"buy_signal_sma_percent50": 0.089
},
"sell": {
"sell_crossed_indicator0": "CDLSHORTLINE-50",
"sell_indicator0": "CDLSEPARATINGLINES-20",
"sell_operator0": "=R",
"sell_percent": 0.01,
"sell_percent3": 0.021,
"sell_percent5": 0.006,
"sell_real_num0": 0.84
},
"protection": {
"lookback": 46,
"lookback_stoploss": 144,
"protection_cooldown": 19,
"protection_max_allowed_dd": 0.36,
"protection_stop": 79,
"protection_stoploss_stop": 13,
"trade_limit": 7,
"trade_limit_stoploss": 5
}
},
"ft_stratparam_v": 1,
"export_time": "2022-02-17 15:42:20.763706+00:00"
}

Some files were not shown because too many files have changed in this diff Show More