A new strategy is added haha
This commit is contained in:
+119
-38
@@ -1,4 +1,5 @@
|
||||
# --- Do not remove these libs ---
|
||||
from statistics import median
|
||||
from freqtrade.strategy import IStrategy
|
||||
import sys
|
||||
import os
|
||||
@@ -6,7 +7,7 @@ import os
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
from ChanLun import ChanLun
|
||||
from ChanLun_Classifier import ChanLunClassifier
|
||||
from ChanEnum import Chan_FX_TYPE, Chan_KLC_FX
|
||||
from ChanEnum import Chan_FX_TYPE, Chan_KLC_FX, Chan_BI_DIR, Chan_KLC_FX
|
||||
# --------------------------------
|
||||
from technical.util import resample_to_interval, resampled_merge
|
||||
import talib.abstract as ta
|
||||
@@ -53,11 +54,17 @@ class ChanLun_SOL_5(IStrategy):
|
||||
"240": 0.052,
|
||||
"360": 0
|
||||
}
|
||||
can_short = True
|
||||
stoploss = -0.20
|
||||
minimal_roi_2 = {
|
||||
"0": 0.10,
|
||||
"1200": 0.05,
|
||||
"2400": 0.025,
|
||||
"3600": 0
|
||||
}
|
||||
can_short = False
|
||||
stoploss = -0.30
|
||||
trailing_stop = False
|
||||
trailing_stop_positive = 0.015
|
||||
trailing_stop_positive_offset = 0.043
|
||||
trailing_stop_positive = 0.025
|
||||
trailing_stop_positive_offset = 0.045
|
||||
trailing_only_offset_is_reached = False
|
||||
|
||||
position_adjustment_enable = True
|
||||
@@ -70,7 +77,7 @@ class ChanLun_SOL_5(IStrategy):
|
||||
time30 = 30
|
||||
time60 = 60
|
||||
time4h = 240
|
||||
time5 = 5
|
||||
time5 = 60
|
||||
last_time = datetime.now()
|
||||
big_size = 0
|
||||
big_state = "00"
|
||||
@@ -102,7 +109,7 @@ class ChanLun_SOL_5(IStrategy):
|
||||
dataframe_60 = self.add_indicators(dataframe_60)
|
||||
dataframe_4h = self.add_indicators(dataframe_4h)
|
||||
dataframe_1d = self.add_indicators(dataframe_1d)
|
||||
dataframe['state'] = self.chan.plot_dataframe(dataframe)
|
||||
dataframe_60['state'] = self.chan.get_klc_state_list(dataframe_60)
|
||||
#dataframe_5['state'] = self.chan.plot_dataframe(dataframe_5)
|
||||
#self.chan.print_data(dataframe_5)
|
||||
#self.chan.cal_qjt(dataframe, dataframe_5)
|
||||
@@ -116,9 +123,10 @@ class ChanLun_SOL_5(IStrategy):
|
||||
self.classifier.train_model(dataframe_1d, model_name="1d_model")
|
||||
"""
|
||||
|
||||
model_name = "5m_model"
|
||||
df = dataframe_5
|
||||
if self.classifier.model is None:
|
||||
model_name = "1m_model"
|
||||
df = dataframe
|
||||
#self.classifier.find_best_params(df, model_name=model_name)
|
||||
if self.classifier.model is None and False:
|
||||
#self.classifier.train_model(df, model_name=model_name, data_file_path=model_name + '_feature_data.csv')
|
||||
self.classifier.load_model(model_name=model_name)
|
||||
klc_list = self.chan.get_klc_list(df)
|
||||
@@ -129,22 +137,21 @@ class ChanLun_SOL_5(IStrategy):
|
||||
bottom_count = 0
|
||||
for index in range(int(len(klc_list) * 0.8), len(klc_list)):
|
||||
klc = klc_list[index]
|
||||
if self.classifier.predict(klc) > 0.37 and (klc.klc_fx_type == Chan_KLC_FX.BOTTOM1 or klc.klc_fx_type == Chan_KLC_FX.BOTTOM2):
|
||||
features = klc.get_feature_data()
|
||||
print(klc.end_time, klc.fx, self.classifier.predict(klc), features['klc_volume_ratio'], features['klc_macd_hist'], features['klc_rsi'])
|
||||
features = klc.get_feature_data()
|
||||
if self.classifier.predict(klc) > 0.5 and (klc.klc_fx_type == Chan_KLC_FX.BOTTOM1 or klc.klc_fx_type == Chan_KLC_FX.BOTTOM2) and features['klc_rsi'] < 40:
|
||||
print(klc.end_time, klc.fx, self.classifier.predict(klc), features['klc_volume_ratio'], features['klc_macdhist'], features['klc_rsi'])
|
||||
bottom_avg += self.classifier.predict(klc)
|
||||
bottom_count += 1
|
||||
if self.classifier.predict(klc) > 0.37 and (klc.klc_fx_type == Chan_KLC_FX.TOP1 or klc.klc_fx_type == Chan_KLC_FX.TOP2):
|
||||
features = klc.get_feature_data()
|
||||
print(klc.end_time, klc.fx, self.classifier.predict(klc), features['klc_volume_ratio'], features['klc_macd_hist'], features['klc_rsi'])
|
||||
if self.classifier.predict(klc) > 0.5 and (klc.klc_fx_type == Chan_KLC_FX.TOP1 or klc.klc_fx_type == Chan_KLC_FX.TOP2) and features['klc_rsi'] > 50:
|
||||
print(klc.end_time, klc.fx, self.classifier.predict(klc), features['klc_volume_ratio'], features['klc_macdhist'], features['klc_rsi'])
|
||||
top_avg += self.classifier.predict(klc)
|
||||
top_count += 1
|
||||
if bottom_count > 0:
|
||||
bottom_avg /= bottom_count
|
||||
if top_count > 0:
|
||||
top_avg /= top_count
|
||||
print(bottom_avg, top_avg)
|
||||
print("-------------------------------------------------------------------------------")
|
||||
print('Bottom:', bottom_avg, 'Top:', top_avg)
|
||||
print("-------------------------------------------------------------------------------")
|
||||
|
||||
"""
|
||||
self.print_xgb(dataframe, "1m_model")
|
||||
@@ -155,7 +162,7 @@ class ChanLun_SOL_5(IStrategy):
|
||||
print("-------------------------------------------------------------------------------")
|
||||
"""
|
||||
|
||||
#classifier.find_best_params(dataframe)
|
||||
|
||||
#classifier.train_model(use_cv=False)
|
||||
#classifier.validate_model(dataframe)
|
||||
#self.chan.get_bsp_list(dataframe)
|
||||
@@ -164,7 +171,7 @@ class ChanLun_SOL_5(IStrategy):
|
||||
#dataframe_30['state'] = self.chan.cal_klu_state(dataframe_30)
|
||||
#dataframe_60['state'] = self.chan.cal_klu_state(dataframe_60)
|
||||
#dataframe_4h['state'] = self.chan.resample_klc_list(dataframe_4h)
|
||||
|
||||
#self.print_bi_klc_fx(dataframe_60, "60m_model")
|
||||
#self.chan.plot_dual(dataframe_5, dataframe_30)
|
||||
dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)
|
||||
#self.print_macd_div_list(dataframe)
|
||||
@@ -176,20 +183,94 @@ class ChanLun_SOL_5(IStrategy):
|
||||
#self.print_klc(dataframe_5, "5m: ")
|
||||
#self.print_klc(dataframe_30, "30m:")
|
||||
#self.log_macd_div_list(dataframe)
|
||||
#self.print_xgb(dataframe, "1m_model")
|
||||
#self.print_xgb(dataframe_5, "5m_model")
|
||||
#self.print_xgb(dataframe_30, "30m_model")
|
||||
#self.print_xgb(dataframe_60, "1h_model")
|
||||
#self.print_xgb(dataframe_4h, "4h_model")
|
||||
self.print_xgb(dataframe, "1m_model")
|
||||
self.print_xgb(dataframe_5, "5m_model")
|
||||
self.print_xgb(dataframe_30, "30m_model")
|
||||
self.print_xgb(dataframe_60, "60m_model")
|
||||
self.print_xgb(dataframe_4h, "4h_model")
|
||||
#self.print_xgb(dataframe_1d, "1d_model")
|
||||
print("-------------------------------------------------------------------------------")
|
||||
self.last_time = datetime.now()
|
||||
#dataframe = resampled_merge(dataframe, dataframe_5)
|
||||
#dataframe = resampled_merge(dataframe, dataframe_15)
|
||||
#dataframe = resampled_merge(dataframe, dataframe_30)
|
||||
#dataframe = resampled_merge(dataframe, dataframe_60)
|
||||
dataframe = resampled_merge(dataframe, dataframe_60)
|
||||
#dataframe = resampled_merge(dataframe, dataframe_4h)
|
||||
return dataframe
|
||||
# This is called when placing the initial order (opening trade)
|
||||
def print_bi_klc_fx(self, dataframe, model_name):
|
||||
klc_list = self.chan.get_full_klc_list(dataframe)
|
||||
bi_list = self.chan.cal_bi_list(klc_list)
|
||||
fx_count_list = []
|
||||
fx_count_list_up = []
|
||||
fx_count_list_down = []
|
||||
self.classifier.load_model(model_name)
|
||||
for bi in bi_list[1:-1]:
|
||||
fx_count = 0
|
||||
if bi.end_klc:
|
||||
for index in range(bi.start_klc.index, bi.end_klc.index+1):
|
||||
klc = klc_list[index]
|
||||
features = klc.get_feature_data()
|
||||
if bi.dir == Chan_BI_DIR.UP and (klc.klc_fx_type == Chan_KLC_FX.TOP1 or klc.klc_fx_type == Chan_KLC_FX.TOP2):
|
||||
fx_count += 1
|
||||
print(klc.start_time, klc.klc_fx_type, self.classifier.predict(klc), bi.dir, features['klc_volume_ratio'], features['klc_macdhist'], features['klc_rsi'])
|
||||
else:
|
||||
if bi.dir == Chan_BI_DIR.DOWN and (klc.klc_fx_type == Chan_KLC_FX.BOTTOM1 or klc.klc_fx_type == Chan_KLC_FX.BOTTOM2):
|
||||
fx_count += 1
|
||||
print(klc.start_time, klc.klc_fx_type, self.classifier.predict(klc), bi.dir, features['klc_volume_ratio'], features['klc_macdhist'], features['klc_rsi'])
|
||||
fx_count_list.append(fx_count)
|
||||
if fx_count == 0:
|
||||
print("Not a bi: ", bi.start_time, bi.end_time, bi.dir)
|
||||
if bi.dir == Chan_BI_DIR.UP:
|
||||
fx_count_list_up.append(fx_count)
|
||||
else:
|
||||
fx_count_list_down.append(fx_count)
|
||||
#print(bi.start_time, bi.end_time, bi.dir, fx_count)
|
||||
avg_count = sum(fx_count_list) / len(fx_count_list)
|
||||
max_count = max(fx_count_list)
|
||||
min_count = min(fx_count_list)
|
||||
median_count = median(fx_count_list)
|
||||
print("Total bi:", len(bi_list), "AVG:", avg_count, "MAX:", max_count, "MIN:", min_count, "MEDIAN:", median_count)
|
||||
for index in range(0, max_count+1):
|
||||
index_count = fx_count_list.count(index)
|
||||
print("Total:", index, "COUNT:", index_count, "RATIO:", index_count/len(fx_count_list))
|
||||
avg_count_up = sum(fx_count_list_up) / len(fx_count_list_up)
|
||||
avg_count_down = sum(fx_count_list_down) / len(fx_count_list_down)
|
||||
median_count_up = median(fx_count_list_up)
|
||||
median_count_down = median(fx_count_list_down)
|
||||
max_count_up = max(fx_count_list_up)
|
||||
min_count_up = min(fx_count_list_up)
|
||||
max_count_down = max(fx_count_list_down)
|
||||
min_count_down = min(fx_count_list_down)
|
||||
print("Total UP bi:", len(fx_count_list_up), "AVG:", avg_count_up, "MAX:", max_count_up, "MIN:", min_count_up, "MEDIAN:", median_count_up)
|
||||
for index in range(0, max_count_up+1):
|
||||
index_count = fx_count_list_up.count(index)
|
||||
print("UP:", index, "COUNT:", index_count, "RATIO:", index_count/len(fx_count_list_up))
|
||||
print("Total DOWN bi:", len(fx_count_list_down), "AVG:", avg_count_down, "MAX:", max_count_down, "MIN:", min_count_down, "MEDIAN:", median_count_down)
|
||||
for index in range(0, max_count_down+1):
|
||||
index_count = fx_count_list_down.count(index)
|
||||
print("DOWN:", index, "COUNT:", index_count, "RATIO:", index_count/len(fx_count_list_down))
|
||||
|
||||
def print_klc_list(self, klc_list, bi_list):
|
||||
bi_index = 0
|
||||
for klc in klc_list:
|
||||
if bi_index == len(bi_list):
|
||||
bi_index = len(bi_list) - 1
|
||||
bi = bi_list[bi_index]
|
||||
if self.check_klc_in_bi(klc, bi):
|
||||
print("KLC in Bi: ", klc.start_time, klc.klc_fx_type, klc.bi.dir, klc.distance, bi.start_time, bi.dir)
|
||||
else:
|
||||
if bi.start_klc.index < klc.index:
|
||||
bi_index += 1
|
||||
print("KLC not in Bi: ", klc.start_time, klc.klc_fx_type, klc.bi.dir, klc.distance, bi.start_time, bi.dir)
|
||||
else:
|
||||
if klc.bi:
|
||||
print("KLC not in Bi: ", klc.start_time, klc.klc_fx_type, klc.bi.dir, klc.distance, bi.start_time, bi.dir)
|
||||
else:
|
||||
print("KLC not in Bi: ", klc.start_time, klc.klc_fx_type, klc.distance, bi.start_time, bi.dir)
|
||||
def check_klc_in_bi(self, klc, bi):
|
||||
if klc.bi and klc.bi.index == bi.index:
|
||||
return True
|
||||
return False
|
||||
def print_xgb(self, dataframe, model_name):
|
||||
self.classifier.load_model(model_name)
|
||||
klc_list = self.chan.get_klc_list(dataframe)
|
||||
@@ -210,7 +291,7 @@ class ChanLun_SOL_5(IStrategy):
|
||||
# We need to leave most of the funds for possible further DCA orders
|
||||
# This also applies to fixed stakes
|
||||
return proposed_stake / self.max_dca_multiplier
|
||||
def adjust_trade_position1(self, trade: Trade, current_time: datetime,
|
||||
def adjust_trade_position(self, trade: Trade, current_time: datetime,
|
||||
current_rate: float, current_profit: float,
|
||||
min_stake: float | None, max_stake: float,
|
||||
current_entry_rate: float, current_exit_rate: float,
|
||||
@@ -282,12 +363,12 @@ class ChanLun_SOL_5(IStrategy):
|
||||
stake_amount = stake_amount * (1 + (count_of_entries * 0.5))
|
||||
dataframe_date = dataframe.iloc[-1]['date']
|
||||
#print(stake_amount, "---------------------------------------------------")
|
||||
if last_entry.order_filled_utc + timedelta(minutes=self.time5) < dataframe_date:
|
||||
if last_entry.order_filled_utc + timedelta(minutes=self.time5*6) < dataframe_date:
|
||||
if dataframe.iloc[-self.time5]['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)] == "-10" and last_entry.side == "buy":
|
||||
#print(dataframe.iloc[-self.time5])
|
||||
#print(stake_amount)
|
||||
return stake_amount, "1/3rd_increase"
|
||||
if last_entry.order_filled_utc + timedelta(minutes=self.time5) < dataframe_date:
|
||||
if last_entry.order_filled_utc + timedelta(minutes=self.time5*6) < dataframe_date:
|
||||
if dataframe.iloc[-self.time5]['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)] == "10" and last_entry.side == "sell":
|
||||
#print(dataframe.iloc[-self.time5])
|
||||
#print(stake_amount)
|
||||
@@ -392,8 +473,8 @@ class ChanLun_SOL_5(IStrategy):
|
||||
|
||||
dataframe.loc[
|
||||
(
|
||||
(dataframe['state'] == "-30")
|
||||
#((dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)] == "-11") |
|
||||
#(dataframe['state'] == "-30")
|
||||
(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)].shift(self.time5) == "-10")
|
||||
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)].shift(self.time5) == "-10") &
|
||||
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time30)] == "-10") &
|
||||
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)].shift(self.time5) == "-10")
|
||||
@@ -402,8 +483,8 @@ class ChanLun_SOL_5(IStrategy):
|
||||
['enter_long', 'enter_tag']] = (1, 'long_signal_chan')
|
||||
dataframe.loc[
|
||||
(
|
||||
(dataframe['state'] == "30")
|
||||
#((dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)] == "11") |
|
||||
#(dataframe['state'] == "30")
|
||||
(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)].shift(self.time5) == "10")
|
||||
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)].shift(self.time5) == "10") &
|
||||
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time30)] == "10") &
|
||||
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)].shift(self.time5) == "10")
|
||||
@@ -414,16 +495,16 @@ class ChanLun_SOL_5(IStrategy):
|
||||
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
dataframe.loc[
|
||||
(
|
||||
(dataframe['state']== "30")
|
||||
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)].shift(self.time5) == "10")
|
||||
#(dataframe['state']== "30")
|
||||
(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)].shift(self.time5) == "10")
|
||||
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time30)] == "10") &
|
||||
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time60)] == "10")
|
||||
),
|
||||
['exit_long', 'exit_tag']] = (1, 'long_close_signal_chan')
|
||||
dataframe.loc[
|
||||
(
|
||||
(dataframe['state'] == "-30")
|
||||
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)].shift(self.time5) == "-10")
|
||||
#(dataframe['state'] == "-30")
|
||||
(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time5)].shift(self.time5) == "-10")
|
||||
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time30)] == "-10") &
|
||||
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time60)] == "-10")
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user