排查回测挣钱,干跑赔钱的问题, 对两边交易结果进行逐条校验
This commit is contained in:
parent
de6c47c3f8
commit
c712c242a7
@ -1,27 +1,27 @@
|
||||
from freqtrade.strategy import IStrategy
|
||||
from pandas import DataFrame
|
||||
import numpy as np # noqa
|
||||
import pandas as pd # noqa
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
import talib.abstract as ta
|
||||
import freqtrade.vendor.qtpylib.indicators as qtpylib
|
||||
|
||||
|
||||
class TheForceV7(IStrategy):
|
||||
INTERFACE_VERSION = 3 # 升级到 V3 接口
|
||||
INTERFACE_VERSION = 3
|
||||
|
||||
minimal_roi = {
|
||||
"0": 10
|
||||
"0": 10
|
||||
}
|
||||
stoploss = -0.1
|
||||
trailing_stop = False
|
||||
timeframe = '5m'
|
||||
process_only_new_candles = True
|
||||
use_exit_signal = True # 替换 use_sell_signal
|
||||
ignore_roi_if_entry_signal = True # 替换 ignore_roi_if_buy_signal
|
||||
use_exit_signal = True
|
||||
ignore_roi_if_entry_signal = True
|
||||
startup_candle_count: int = 30
|
||||
order_types = {
|
||||
'entry': 'limit', # 替换 buy
|
||||
'exit': 'limit', # 替换 sell
|
||||
'entry': 'limit',
|
||||
'exit': 'limit',
|
||||
'stoploss': 'market',
|
||||
'stoploss_on_exchange': False
|
||||
}
|
||||
@ -46,10 +46,17 @@ class TheForceV7(IStrategy):
|
||||
}
|
||||
}
|
||||
|
||||
def __init__(self, config: dict) -> None:
|
||||
super().__init__(config)
|
||||
self.trade_data = {} # 用于缓存 K 线数据以计算 min_rate 和 max_rate
|
||||
|
||||
def informative_pairs(self):
|
||||
return []
|
||||
|
||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
# 缓存 K 线数据
|
||||
self.trade_data[metadata['pair']] = dataframe
|
||||
|
||||
stoch = ta.STOCH(dataframe)
|
||||
dataframe['slowd'] = stoch['slowd']
|
||||
dataframe['slowk'] = stoch['slowk']
|
||||
@ -79,32 +86,32 @@ class TheForceV7(IStrategy):
|
||||
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
dataframe.loc[
|
||||
(
|
||||
(
|
||||
(
|
||||
(
|
||||
(dataframe['slowk'] >= 20) & (dataframe['slowk'] <= 80)
|
||||
&
|
||||
(dataframe['slowd'] >= 20) & (dataframe['slowd'] <= 80)
|
||||
)
|
||||
|
|
||||
(
|
||||
(
|
||||
(dataframe['slowk'] < 30) & (dataframe['slowd'] < 30) &
|
||||
(qtpylib.crossed_above(dataframe['slowk'], dataframe['slowd']))
|
||||
)
|
||||
)
|
||||
&
|
||||
(
|
||||
(
|
||||
(dataframe['macd'] > dataframe['macd'].shift(1))
|
||||
&
|
||||
(dataframe['macdsignal'] > dataframe['macdsignal'].shift(1))
|
||||
)
|
||||
&
|
||||
(
|
||||
(
|
||||
(dataframe['close'] > dataframe['close'].shift(1))
|
||||
&
|
||||
(dataframe['open'] > dataframe['open'].shift(1))
|
||||
(dataframe['open'] > dataframe['open'].shift(1))
|
||||
)
|
||||
&
|
||||
(
|
||||
(
|
||||
(dataframe['ema5c'] >= dataframe['ema5o'])
|
||||
|
|
||||
(dataframe['open'] < dataframe['ema5l'])
|
||||
@ -114,7 +121,7 @@ class TheForceV7(IStrategy):
|
||||
(dataframe['volume'] > dataframe['volvar'])
|
||||
)
|
||||
|
|
||||
(
|
||||
(
|
||||
(dataframe['slowk'] >= 20) & (dataframe['slowk'] <= 80)
|
||||
&
|
||||
(dataframe['slowd'] >= 20) & (dataframe['slowd'] <= 80)
|
||||
@ -126,8 +133,8 @@ class TheForceV7(IStrategy):
|
||||
)
|
||||
)
|
||||
|
|
||||
(
|
||||
(dataframe['close'] > dataframe['ema200c'])
|
||||
(
|
||||
(dataframe['close'] > dataframe['ema200c'])
|
||||
&
|
||||
(dataframe['rsi7'] < 35)
|
||||
)
|
||||
@ -138,37 +145,37 @@ class TheForceV7(IStrategy):
|
||||
|
||||
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
dataframe.loc[
|
||||
(
|
||||
(
|
||||
(
|
||||
(
|
||||
(dataframe['slowk'] <= 80) & (dataframe['slowd'] <= 80)
|
||||
(dataframe['slowk'] <= 80) & (dataframe['slowd'] <= 80)
|
||||
)
|
||||
|
|
||||
(
|
||||
(
|
||||
(qtpylib.crossed_above(dataframe['slowk'], 70))
|
||||
|
|
||||
(qtpylib.crossed_above(dataframe['slowd'], 70))
|
||||
)
|
||||
)
|
||||
&
|
||||
(
|
||||
(
|
||||
(dataframe['macd'] < dataframe['macd'].shift(1))
|
||||
&
|
||||
(dataframe['macdsignal'] < dataframe['macdsignal'].shift(1))
|
||||
)
|
||||
&
|
||||
(
|
||||
(
|
||||
(dataframe['ema5c'] < dataframe['ema5o'])
|
||||
|
|
||||
(dataframe['open'] >= dataframe['ema5h'])
|
||||
(dataframe['open'] >= dataframe['ema5h'])
|
||||
)
|
||||
|
|
||||
(
|
||||
(
|
||||
(dataframe['slowk'] <= 80)
|
||||
&
|
||||
(dataframe['slowd'] <= 80)
|
||||
&
|
||||
(
|
||||
(
|
||||
(dataframe['close'] >= dataframe['bb_upperband'])
|
||||
|
|
||||
(dataframe['open'] >= dataframe['bb_upperband'])
|
||||
@ -180,8 +187,40 @@ class TheForceV7(IStrategy):
|
||||
&
|
||||
(((dataframe['high'] - dataframe['bb_upperband']) * 100 / dataframe['bb_upperband']) > 1)
|
||||
)
|
||||
|
||||
),
|
||||
'exit_long'] = 1
|
||||
return dataframe
|
||||
|
||||
def confirm_trade_entry(self, pair: str, order_type: str, amount: float, rate: float,
|
||||
time: str, current_time: 'datetime', **kwargs) -> bool:
|
||||
log_path = '/freqtrade/user_data/dryrun_results/dry_run_trades.csv'
|
||||
# 自动创建目录
|
||||
os.makedirs(os.path.dirname(log_path), exist_ok=True)
|
||||
# 写入日志
|
||||
with open(log_path, 'a') as f:
|
||||
f.write(f"{pair},{current_time},,,{rate},,{amount},,,,,,,,\n")
|
||||
return True
|
||||
|
||||
|
||||
def confirm_trade_exit(self, pair: str, trade: 'Trade', order_type: str, amount: float,
|
||||
rate: float, time: str, exit_reason: str, current_time: 'datetime', **kwargs) -> bool:
|
||||
log_path = '/freqtrade/user_data/dryrun_results/dry_run_trades.csv'
|
||||
# 自动创建目录
|
||||
os.makedirs(os.path.dirname(log_path), exist_ok=True)
|
||||
# 计算盈亏
|
||||
profit_ratio = trade.calc_profit_ratio(rate)
|
||||
profit_abs = trade.calc_profit(rate)
|
||||
trade_duration = (current_time - trade.open_date).total_seconds() / 60
|
||||
# 获取 min_rate 和 max_rate
|
||||
df = self.trade_data.get(pair)
|
||||
min_rate = max_rate = rate
|
||||
if df is not None:
|
||||
trade_period = df[(df['date'] >= trade.open_date) & (df['date'] <= current_time)]
|
||||
min_rate = trade_period['low'].min() if not trade_period.empty else rate
|
||||
max_rate = trade_period['high'].max() if not trade_period.empty else rate
|
||||
# 写入日志
|
||||
with open(log_path, 'a') as f:
|
||||
f.write(f"{pair},{trade.open_date},{current_time},{trade.open_rate},{rate},"
|
||||
f"{amount},{profit_ratio},{profit_abs},{exit_reason},"
|
||||
f"{trade.fee_open},{trade.fee_close},{trade_duration},{min_rate},{max_rate}\n")
|
||||
return True
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user