# DevilStra Strategy # 𝔇𝔒𝔳𝔦𝔩 𝔦𝔰 π”žπ”©π”΄π”žπ”Άπ”° 𝔰𝔱𝔯𝔬𝔫𝔀𝔒𝔯 𝔱π”₯π”žπ”« π”Šπ”¬π”‘. # 𝔅𝔲𝔱 𝔱π”₯𝔒 𝔬𝔫𝔩𝔢 𝔬𝔫𝔒 𝔴π”₯𝔬 π”₯π”žπ”° 𝔱π”₯𝔒 π”žπ”Ÿπ”¦π”©π”¦π”±π”Ά # 𝔱𝔬 π” π”―π”’π”žπ”±π”’ 𝔫𝔒𝔴 π” π”―π”’π”žπ”±π”²π”―π”’π”° 𝔦𝔰 π”Šπ”¬π”‘. # 𝔄𝔫𝔑 𝔱π”₯𝔒 𝔑𝔒𝔳𝔦𝔩 π”ͺπ”žπ”¨π”’π”° 𝔭𝔬𝔴𝔒𝔯𝔣𝔲𝔩 𝔰𝔭𝔒𝔩𝔩𝔰 # 𝔣𝔯𝔬π”ͺ 𝔱π”₯𝔦𝔰 𝔰π”ͺπ”žπ”©π”© π” π”―π”’π”žπ”±π”²π”―π”’π”° (𝔩𝔦𝔨𝔒 𝔣𝔯𝔬𝔀𝔰, 𝔒𝔱𝔠.) # 𝔱𝔬 π”ͺπ”žπ”¨π”’ π”₯𝔦𝔰 𝔰𝔭𝔒𝔩𝔩𝔰 𝔴𝔦𝔱π”₯ π”‰π”―π”žπ”€π”ͺπ”’π”«π”±π”žπ”±π”¦π”¬π”« π”žπ”«π”‘ π”ͺ𝔦𝔡𝔦𝔫𝔀 𝔱π”₯𝔒π”ͺ. # Author: @Mablue (Masoud Azizi) # github: https://github.com/mablue/ # freqtrade hyperopt --hyperopt-loss SharpeHyperOptLoss --spaces buy sell --strategy GodStraNew # --- Do not remove these libs --- import random from freqtrade.strategy.hyper 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 # TODO: this gene is removed 'MAVP' cuz or error on periods ########################### SETTINGS ############################## # you can find exact value of is inside GodStra TREND_CHECK_CANDLES = 4 # Set the pain range of devil(2~infinite) PAIN_RANGE = 30000 # Add GodStra Generated Results As spells inside SPELLS. # Set them unic phonemes like 'Zi' 'Gu' or 'Lu'! # * Use below replacement on GodStra results to # * Change God Generated Creatures to Spells: # +--------------------------+----------------------+ # | GodStra 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", "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, } }, "A": { "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": "/", "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": " 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].div(dataframe[crossed_indicator]) > real_num ) elif operator == "/=R": condition = ( np.isclose(dataframe[indicator].div(dataframe[crossed_indicator]), real_num) ) elif operator == "/ 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): # #################### RESULTS PASTE PLACE #################### # * 11/1000: 123 trades. 80/0/43 Wins/Draws/Losses. Avg profit 18.06%. Median profit 7.08%. Total profit 0.02199610 BTC ( 22.00Ξ£%). Avg duration 22 days, 18:28:00 min. Objective: -36.39438 # Buy hyperspace params: buy_params = { "buy_spell": ('Lu', 'Lu', 'Si', 'Pa', 'Zi', 'Si', 'Gu', 'Zi', 'Si', 'Gu', 'Ra', 'Lu', 'Gu', 'A', 'Pa', 'A', 'Zi', 'De', 'Cu', 'Gu', 'Cu', 'Ra', 'Cu', 'Pa', 'Lu', 'Gu', 'Cu', 'Zi', 'Si', 'Zi', 'Cu', 'A', 'Ra', 'De', 'Si', 'Zi', 'A', 'Ra', 'Gu', 'De', 'De', 'Lu', 'Si', 'Gu', 'Gu', 'Pa', 'De', 'Lu', 'Si', 'Zi', 'Pa', 'Si', 'Gu', 'Zi', 'De', 'Cu', 'Gu', 'Si', 'Pa', 'Pa', 'Si', 'A', 'Zi', 'De', 'Ra', 'Si', 'Gu', 'Si', 'De', 'Gu', 'Pa', 'De', 'A', 'Si', 'De', 'Pa', 'Ra', 'Zi', 'De', 'Pa', 'Zi', 'Ra', 'A', 'Cu', 'Pa', 'Pa', 'Lu', 'Pa', 'De', 'Gu', 'Gu', 'Ra', 'Lu', 'De', 'Cu', 'Ra', 'Zi', 'Si', 'Ra', 'Lu', 'De', 'A', 'Zi', 'Cu', 'Gu', 'Pa', 'De', 'Ra', 'Pa', 'Pa', 'A', 'Si', 'Ra', 'Cu', 'De', 'Gu', 'Si', 'Gu', 'Zi', 'Cu', 'A', 'Lu', 'Lu', 'A', 'Si', 'Pa', 'Zi', 'Zi', 'Cu', 'Ra', 'Lu', 'Ra', 'De', 'De', 'A', 'Si', 'Pa', 'De', 'Lu', 'Pa', 'De', 'Ra', 'Ra', 'Pa', 'Pa', 'Gu', 'Gu', 'Ra', 'Gu', 'Ra', 'Pa', 'Lu', 'A', 'Zi', 'Gu', 'Lu', 'Lu', 'Zi', 'Gu', 'A', 'Ra', 'Gu', 'Zi', 'Si', 'A', 'Cu', 'Pa', 'De', 'Lu', 'Cu', 'A', 'Zi', 'A', 'Lu', 'Lu', 'Gu', 'Pa', 'Gu', 'A', 'Gu', 'Gu', 'Cu', 'Si', 'Lu', 'Zi', 'De', 'Gu', 'Zi', 'Si', 'Ra', 'De', 'Pa', 'Gu', 'Gu', 'Zi', 'Lu', 'Zi', 'Lu', 'Si', 'Zi', 'Gu', 'Si', 'Ra', 'Lu', 'Pa', 'A', 'A', 'Lu', 'Pa', 'De', 'De', 'Cu', 'Ra', 'Lu', 'De', 'Si', 'Cu', 'Si', 'Si', 'Zi', 'De', 'Si', 'Si', 'Cu', 'Gu', 'Si', 'Ra', 'Si', 'Cu', 'A', 'Zi', 'De', 'Gu', 'Pa', 'Lu', 'Cu', 'Cu', 'Pa', 'Cu', 'A', 'Si', 'Zi', 'Cu', 'Zi', 'Ra', 'Si', 'Lu', 'Lu', 'De', 'Cu', 'Cu', 'Lu', 'Pa', 'Ra', 'Cu', 'Lu', 'Ra', 'Zi', 'Gu', 'Ra', 'Cu', 'A', 'De', 'Cu', 'Ra', 'Ra', 'De', 'Zi', 'De', 'De', 'A', 'Pa', 'A', 'Gu', 'Lu', 'De', 'De', 'A', 'Pa', 'Gu', 'Gu', 'De', 'Gu', 'Cu', 'Zi', 'Si', 'Gu', 'Ra', 'Pa', 'Gu', 'Lu', 'A', 'Lu', 'A', 'Si', 'Si', 'Pa', 'Ra', 'Cu', 'Lu'), } # Sell hyperspace params: sell_params = { "sell_spell": ('A', 'Lu', 'Lu', 'Cu', 'De', 'Zi', 'Si', 'Lu', 'Cu', 'A', 'A', 'Pa', 'Si', 'Pa', 'Si', 'Zi', 'Si', 'Zi', 'Pa', 'Cu', 'Zi', 'A', 'De', 'Si', 'A', 'Gu', 'Gu', 'Pa', 'Lu', 'Ra', 'De', 'Gu', 'Pa', 'Gu', 'Ra', 'Gu', 'Gu', 'Zi', 'Lu', 'Gu', 'Ra', 'Si', 'Lu', 'Ra', 'Zi', 'De', 'Gu', 'Ra', 'Si', 'Ra', 'De', 'Si', 'Ra', 'Cu', 'Lu', 'Lu', 'Ra', 'Cu', 'A', 'De', 'Pa', 'Cu', 'Pa', 'Pa', 'A', 'Zi', 'Lu', 'Zi', 'Lu', 'Si', 'A', 'Lu', 'Zi', 'Pa', 'Gu', 'Ra', 'Zi', 'De', 'Cu', 'A', 'Si', 'Gu', 'De', 'Cu', 'De', 'Ra', 'Cu', 'Si', 'Gu', 'De', 'Cu', 'Pa', 'Si', 'Zi', 'Cu', 'Lu', 'Lu', 'Si', 'Cu', 'Zi', 'A', 'Pa', 'De', 'Zi', 'Si', 'Si', 'Cu', 'Pa', 'Zi', 'Si', 'Si', 'Lu', 'Pa', 'Lu', 'De', 'Si', 'Cu', 'Cu', 'Zi', 'Gu', 'Si', 'Ra', 'Pa', 'Gu', 'Gu', 'Lu', 'Pa', 'Cu', 'Zi', 'Pa', 'Si', 'Ra', 'A', 'Gu', 'Pa', 'A', 'A', 'A', 'A', 'Si', 'Cu', 'Gu', 'De', 'Pa', 'De', 'Cu', 'Zi', 'Pa', 'A', 'Cu', 'Zi', 'Gu', 'Gu', 'Lu', 'Zi', 'A', 'Gu', 'Pa', 'Lu', 'Si', 'Zi', 'A', 'A', 'Pa', 'Gu', 'Zi', 'De', 'Ra', 'De', 'Cu', 'Ra', 'Pa', 'Pa', 'Lu', 'Zi', 'Si', 'Gu', 'Zi', 'Ra', 'De', 'Cu', 'Zi', 'Cu', 'Gu', 'De', 'Lu', 'A', 'A', 'Si', 'De', 'Si', 'Zi', 'Gu', 'Si', 'Cu', 'Ra', 'Lu', 'Lu', 'De', 'Gu', 'Cu', 'Pa', 'Ra', 'Lu', 'Si', 'Ra', 'Gu', 'Cu', 'De', 'Si', 'Pa', 'Gu', 'Zi', 'Si', 'A', 'Cu', 'Lu', 'Si', 'Si', 'Zi', 'Si', 'Gu', 'A', 'Cu', 'A', 'Gu', 'A', 'Zi', 'Ra', 'Zi', 'Zi', 'Zi', 'Ra', 'Gu', 'De', 'Zi', 'Ra', 'Zi', 'A', 'De', 'De', 'Ra', 'A', 'Gu', 'De', 'Lu', 'Cu', 'Gu', 'Si', 'A', 'Cu', 'Lu', 'Cu', 'A', 'Zi', 'De', 'Gu', 'Si', 'Zi', 'Gu', 'Pa', 'Si', 'Gu', 'Lu', 'Cu', 'Gu', 'De', 'Cu', 'Cu', 'Ra', 'Gu', 'Pa', 'Cu', 'De', 'De', 'Zi', 'Pa', 'A', 'Cu', 'Zi', 'A', 'Zi', 'De', 'Lu', 'Cu', 'Cu', 'De', 'Cu', 'Ra', 'Ra', 'Zi', 'Si', 'Cu', 'Ra', 'De', 'Cu', 'Gu', 'Lu', 'Pa', 'Gu'), } # #################### END OF RESULT PLACE #################### spell_pot = [ tuple( random.choices( list(SPELLS.keys()), # TODO: k will be change to len(pairlist) k=300 ) )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') # Stoploss: stoploss = -0.1 # Buy hypers timeframe = '1h' 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() pair_index = pairs.index(metadata['pair']) buy_params_index = self.buy_spell.value[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() pair_index = pairs.index(metadata['pair']) sell_params_index = self.sell_spell.value[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