Start to integration strategy

This commit is contained in:
Porter
2025-06-14 13:58:02 +08:00
parent 20a633910d
commit 11f9863e75
3 changed files with 162 additions and 32 deletions
+87 -23
View File
@@ -14,7 +14,7 @@ from technical.util import resample_to_interval, resampled_merge
import talib.abstract as ta
from pandas import DataFrame
from datetime import datetime, timedelta
from freqtrade.persistence import Trade
from freqtrade.persistence import Trade, Order
from typing import Optional
import logging
logger = logging.getLogger(__name__)
@@ -42,14 +42,14 @@ class ChanLun_BTC_30(IStrategy):
"1200": 0
}
# 5m and 15m
minimal_roi_1 = {
minimal_roi = {
"0": 0.1,
"60": 0.05,
"120": 0.02,
"240": 0
}
# 15m and 30m
minimal_roi_1 = {
minimal_roi = {
"0": 0.1,
"240": 0.05,
"480": 0.03,
@@ -62,12 +62,12 @@ class ChanLun_BTC_30(IStrategy):
"3600": 0
}
can_short = True
lev = 1.0
lev = 2.0
stoploss = -0.3
trailing_stop = False
trailing_stop = True
trailing_stop_positive = 0.025
trailing_stop_positive_offset = 0.045
trailing_only_offset_is_reached = False
trailing_only_offset_is_reached = True
position_adjustment_enable = True
startup_candle_count = 600
@@ -81,6 +81,7 @@ class ChanLun_BTC_30(IStrategy):
chan = ChanLun()
chanpy = ChanPY()
classifier = ChanLunClassifier(None)
last_trade = None
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# resample our dataframes
@@ -104,17 +105,13 @@ class ChanLun_BTC_30(IStrategy):
dataframe_4h = self.add_indicators(dataframe_4h)
dataframe_1d = self.add_indicators(dataframe_1d)
#self.chan.plot_dual(dataframe_5, dataframe_30)
dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)
dataframe_5['chanpy_state'] = self.chanpy.get_bsp_state(dataframe_5)
state_list, fx_list = self.chan.get_klc_strength_list(dataframe_30)
dataframe_30['state'] = state_list
dataframe_30['fx'] = fx_list
klc_list = self.chan.get_klc_list(dataframe_30)
bi_list = self.chan.cal_bi_list(klc_list)
if self.last_time + timedelta(minutes=1) < datetime.now():
print(state_list[-1], state_list[-2], state_list[-3], state_list[-4], state_list[-5])
print(fx_list[-1], fx_list[-2], fx_list[-3], fx_list[-4], fx_list[-5])
print(klc_list[-1].klc_fx_type, klc_list[-2].klc_fx_type, klc_list[-3].klc_fx_type, klc_list[-4].klc_fx_type, klc_list[-5].klc_fx_type)
print("-------------------------------------------------------------------------------")
self.last_time = datetime.now()
dataframe = resampled_merge(dataframe, dataframe_5)
@@ -168,18 +165,84 @@ class ChanLun_BTC_30(IStrategy):
else:
new_exitprice = proposed_rate - 50
return new_exitprice
def confirm_trade_entry(self, pair: str, order_type: str, amount: float, rate: float,
time_in_force: str, current_time: datetime, entry_tag: str | None,
side: str, **kwargs) -> bool:
if self.last_trade:
if self.last_trade.open_date + timedelta(minutes=30) > current_time:
return False
#if self.last_trade:
#print(self.last_trade.open_date, current_time, self.last_trade.open_date + timedelta(minutes=self.time5))
return True
def custom_exit(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()
"""
# Above 20% profit, sell when rsi < 80
if current_profit > 0.2:
if last_candle["rsi"] < 80:
return "rsi_below_80"
# Between 2% and 10%, sell if EMA-long above EMA-short
if 0.02 < current_profit < 0.1:
if last_candle["emalong"] > last_candle["emashort"]:
return "ema_long_below_80"
# Sell any positions at a loss if they are held for more than one day.
if current_profit < 0.0 and (current_time - trade.open_date_utc).days >= 1:
return "unclog"
"""
if trade.is_short:
last_high = trade.get_custom_data(key="entry_candle_high")
if current_rate > last_high:
print(trade.open_date, last_high, current_rate, "Relay Top FX exit")
return "Relay Top FX exit"
else:
last_low = trade.get_custom_data(key="entry_candle_low")
if current_rate < last_low:
print(trade.open_date, last_low, current_rate, "Relay Bottom FX exit")
return "Relay Bottom FX exit"
def order_filled(self, pair: str, trade: Trade, order: Order, current_time: datetime, **kwargs) -> None:
"""
Called right after an order fills.
Will be called for all order types (entry, exit, stoploss, position adjustment).
:param pair: Pair for trade
:param trade: trade object.
:param order: Order object.
:param current_time: datetime object, containing the current datetime
:param **kwargs: Ensure to keep this here so updates to this won't break your strategy.
"""
# Obtain pair dataframe (just to show how to access it)
dataframe, _ = self.dp.get_analyzed_dataframe(trade.pair, self.timeframe)
#last_candle = dataframe.iloc[-1].squeeze()
klc_list = self.chan.get_klc_list(resample_to_interval(dataframe, self.get_ticker_indicator() * 30))
bi_list = self.chan.cal_bi_list(klc_list)
last_high = klc_list[-3].high
last_low = klc_list[-3].low
if trade.is_short:
if (trade.nr_of_successful_entries == 1) and (order.ft_order_side == trade.entry_side):
trade.set_custom_data(key="entry_candle_high", value=last_high)
else:
if (trade.nr_of_successful_entries == 1) and (order.ft_order_side == trade.entry_side):
trade.set_custom_data(key="entry_candle_low", value=last_low)
print(trade.open_date, trade.close_date, last_high, last_low, order.ft_order_side, klc_list[-2].start_time, klc_list[-2].end_time)
self.last_trade = trade
return None
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
state_str = 'resample_{}_state'.format(self.get_ticker_indicator()*self.time30)
fx_str = 'resample_{}_fx'.format(self.get_ticker_indicator()*self.time30)
chanpy_state_str = 'resample_{}_chanpy_state'.format(self.get_ticker_indicator()*self.time5)
shift_time = self.time30
shift_time = self.time30*2
strength = 2.2
dataframe.loc[
(
#(dataframe['state'] == "-30")
(dataframe[state_str].shift(shift_time) > 1.0) &
(dataframe[state_str].shift(shift_time) > strength) &
(dataframe[fx_str].shift(shift_time) == -1) &
(dataframe[chanpy_state_str].shift(shift_time) == 1)
(dataframe[chanpy_state_str].shift(shift_time+10) == 1)
#(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")
@@ -189,9 +252,9 @@ class ChanLun_BTC_30(IStrategy):
dataframe.loc[
(
#(dataframe['state'] == "-30")
(dataframe[state_str].shift(shift_time) > 1.0) &
(dataframe[state_str].shift(shift_time) > strength) &
(dataframe[fx_str].shift(shift_time) == 1) &
(dataframe[chanpy_state_str].shift(shift_time) == -1)
(dataframe[chanpy_state_str].shift(shift_time+10) == -1)
#(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")
@@ -203,13 +266,14 @@ class ChanLun_BTC_30(IStrategy):
state_str = 'resample_{}_state'.format(self.get_ticker_indicator()*self.time30)
fx_str = 'resample_{}_fx'.format(self.get_ticker_indicator()*self.time30)
chanpy_state_str = 'resample_{}_chanpy_state'.format(self.get_ticker_indicator()*self.time5)
shift_time = self.time30
shift_time = self.time30*2
strength = 2.2
dataframe.loc[
(
#(dataframe['state']== "30")
(dataframe[state_str].shift(shift_time) > 1.0) &
(dataframe[state_str].shift(shift_time) > strength) &
(dataframe[fx_str].shift(shift_time) == 1) &
(dataframe[chanpy_state_str].shift(shift_time) == -1)
(dataframe[chanpy_state_str].shift(shift_time+10) == -1)
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time30)] == "10") &
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time60)] == "10")
),
@@ -217,9 +281,9 @@ class ChanLun_BTC_30(IStrategy):
dataframe.loc[
(
#(dataframe['state']== "30")
(dataframe[state_str].shift(shift_time) > 1.0) &
(dataframe[state_str].shift(shift_time) > strength) &
(dataframe[fx_str].shift(shift_time) == -1) &
(dataframe[chanpy_state_str].shift(shift_time) == 1)
(dataframe[chanpy_state_str].shift(shift_time+10) == 1)
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time30)] == "10") &
#(dataframe['resample_{}_state'.format(self.get_ticker_indicator()*self.time60)] == "10")
),