610 lines
23 KiB
Python
610 lines
23 KiB
Python
# 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
|
|
|