约定规范

This commit is contained in:
zhangkun9038@dingtalk.com 2025-05-12 09:56:13 +00:00
parent e558c1b0bd
commit 2a7d94cd23
14 changed files with 680 additions and 21938 deletions

2
.gitignore vendored
View File

@ -122,3 +122,5 @@ docker-compose-*.yml
data/
!result/
output.log
output_filted.log

30
backtest.sh Executable file
View File

@ -0,0 +1,30 @@
#!/bin/bash
rm -rf user_data/models/*
rm -rf ./freqtrade/user_data/data/backtest_results/*
docker-compose -f docker-compose_backtest.yml run --rm freqtrade >output.log 2>&1
sed -i 's/\x1B\[[0-9;]*m//g' output.log
python3 filter.py
rm ./result/* -fr
mv ./user_data/backtest_results/* ./result/
cd ./result
# 查找当前目录下的所有 zip 文件
zip_files=(*.zip)
# 检查是否只有一个 zip 文件
if [ ${#zip_files[@]} -eq 1 ]; then
# 解压缩该 zip 文件到当前目录
unzip "${zip_files[0]}"
rm *.zip
rm *.feather
else
echo "当前目录下没有 zip 文件或者有多个 zip 文件,无法操作。"
fi
cd -
sed -i 's/\x1B\[[0-9;]*m//g' output.log
python3 filter.py
cp output_filted.log result/ -f

View File

@ -10,7 +10,7 @@
"fiat_display_currency": "USD",
"dry_run": true,
"identifier": "demo1",
"timeframe": "3m",
"timeframe": "5m",
"dry_run_wallet": 1000,
"cancel_open_orders_on_exit": true,
"stoploss": -0.05,
@ -36,7 +36,12 @@
"timeout": 20000
},
"pair_whitelist": [
"OKB/USDT"
"OKB/USDT",
"BTC/USDT",
"SOL/USDT",
"DOT/USDT",
"TON/USDT",
"ETH/USDT",
],
"pair_blacklist": []
},

View File

@ -0,0 +1,132 @@
{
"$schema": "https://schema.freqtrade.io/schema.json",
"trading_mode": "spot",
"margin_mode": "isolated",
"max_open_trades": 4,
"stake_currency": "USDT",
"stake_amount": 150,
"startup_candle_count": 400,
"tradable_balance_ratio": 1,
"fiat_display_currency": "USD",
"dry_run": true,
"identifier": "demo1",
"timeframe": "5m",
"dry_run_wallet": 1000,
"cancel_open_orders_on_exit": true,
"stoploss": -0.1,
"unfilledtimeout": {
"entry": 5,
"exit": 15
},
"exchange": {
"name": "okx",
"key": "eca767d4-fda5-4a1b-bb28-49ae18093307",
"secret": "8CA3628A556ED137977DB298D37BC7F3",
"enable_ws": false,
"ccxt_config": {
"enableRateLimit": true,
"rateLimit": 500,
"options": {
"defaultType": "spot"
}
},
"ccxt_async_config": {
"enableRateLimit": true,
"rateLimit": 3000,
"timeout": 20000
},
"pair_whitelist": [
"OKB/USDT",
"BTC/USDT",
"ETH/USDT",
"SOL/USDT",
"DOT/USDT"
],
"pair_blacklist": []
},
"freqai": {
"enabled": true,
"identifier": "test175",
"freqaimodel": "XGBoostRegressor",
"model_path": "/freqtrade/user_data/models",
"save_backtesting_prediction": true,
"save_backtest_models": true,
"backtest_period_days": 30,
"purge_old_models": true,
"load_trained_model": true,
"train_period_days": 90,
"backtest_period_days": 10,
"live_retrain_hours": 0,
"include_predictions_in_final_dataframe": true,
"data_kitchen": {
"fillna": "ffill",
"feature_parameters": {
"DI_threshold": 0.5,
"weight_factor": 0.9
}
},
"feature_parameters": {
"include_timeframes": ["5m", "15m", "1h"],
"include_corr_pairlist": ["BTC/USDT", "ETH/USDT"],
"label_period_candles": 12,
"include_shifted_candles": 3,
"indicator_periods_candles": [10, 20, 50],
"plot_feature_importances": 1,
"feature_selection": {
"method": "none"
}
},
"data_split_parameters": {
"test_size": 0.2,
"shuffle": false
},
"model_training_parameters": {
"n_estimators": 200,
"learning_rate": 0.05,
"max_depth": 6,
"subsample": 0.8,
"colsample_bytree": 0.8
}
},
"entry_pricing": {
"price_side": "same",
"use_order_book": true,
"order_book_top": 1,
"price_last_balance": 0.0,
"check_depth_of_market": {
"enabled": false,
"bids_to_ask_delta": 1
}
},
"exit_pricing": {
"price_side": "other",
"use_order_book": true,
"order_book_top": 1
},
"pairlists": [
{
"method": "StaticPairList"
}
],
"api_server": {
"enabled": true,
"listen_ip_address": "0.0.0.0",
"listen_port": 8080,
"verbosity": "error",
"enable_openapi": false,
"jwt_secret_key": "6a599ab046dbb419014807dffd7b8823bfa7e5df56b17d545485deb87331b4ca",
"ws_token": "6O5pBDiRigiZrmIsofaE2rkKMJtf9h8zVQ",
"CORS_origins": [],
"username": "freqAdmin",
"password": "admin"
},
"use_exit_signal": true,
"bot_name": "freqtrade",
"initial_state": "running",
"force_entry_enable": false,
"internals": {
"process_throttle_secs": 5,
"heartbeat_interval": 20,
"loglevel": "DEBUG"
}
}

View File

@ -67,7 +67,7 @@ services:
backtesting
--logfile /freqtrade/user_data/logs/freqtrade.log
--freqaimodel XGBoostRegressor
--config /freqtrade/config_examples/nb.json
--config /freqtrade/config_examples/theforcev7.json
--strategy-path /freqtrade/templates
--strategy TheForceV7
--timerange 20240901-20250315

View File

@ -0,0 +1,87 @@
---
services:
freqtrade:
image: freqtradeorg/freqtrade:develop_freqaitorch
# # Enable GPU Image and GPU Resources
# # Make sure to uncomment the whole deploy section
# deploy:
# resources:
# reservations:
# devices:
# - driver: nvidia
# count: 1
# capabilities: [gpu]
# Build step - only needed when additional dependencies are needed
# build:
# context: .
# dockerfile: "./docker/Dockerfile.custom"
restart: always
container_name: freqtrade
volumes:
- "./user_data:/freqtrade/user_data"
- "./config_examples:/freqtrade/config_examples"
- "./freqtrade/templates:/freqtrade/templates"
- "./freqtrade/exchange/:/freqtrade/exchange"
# Expose api on port 8080 (localhost only)
# Please read the https://www.freqtrade.io/en/stable/rest-api/ documentation
# for more information.
ports:
- "8080:8080"
# Default command used when running `docker compose up`
# --freqaimodel XGBoostRegressor
# commangd: >
# # trade
# --logfile /freqtrade/user_data/logs/freqtrade.log
# --db-url sqlite:////freqtrade/user_data/tradesv3.sqlite
# --freqaimodel LightGBMRegressor
# --config /freqtrade/config_examples/config_freqai.okx.json
# --strategy FreqaiExampleStrategy
# --strategy FreqaiExampleHybridStrategy
# --strategy-path /freqtrade/templates
# command: >
# backtesting
# --logfile /freqtrade/user_data/logs/freqtrade.log
# --freqaimodel XGBoostRegressor
# --config /freqtrade/config_examples/config_freqai.okx.json
# --strategy-path /freqtrade/templates
# --strategy FreqaiExampleStrategy
# --timerange 20250310-20250410
# --export trades
# command: >
# hyperopt
# --logfile /freqtrade/user_data/logs/freqtrade.log
# --freqaimodel LightGBMRegressor
# --config /freqtrade/config_examples/config_freqai.okx.json
# --strategy-path /freqtrade/templates
# --strategy FreqaiExampleStrategy
# --timerange 20250301-20250420
# --hyperopt-loss SharpeHyperOptLoss
# --spaces roi stoploss
# -e 200
#--config /freqtrade/templates/FreqaiExampleStrategy.json
command: >
backtesting
--logfile /freqtrade/user_data/logs/freqtrade.log
--freqaimodel XGBoostRegressor
--config /freqtrade/config_examples/config_my_hyperopt.json
--strategy-path /freqtrade/templates
--strategy TheForceV7
--timerange 20240101-20250413
--breakdown week month
--export trades
--fee 0.0008
--cache none
# command: >
# trade
# --logfile /freqtrade/user_data/logs/freqtrade.log
# --db-url sqlite:////freqtrade/user_data/tradesv3.sqlite
# --freqaimodel XGBoostRegressor
# --config /freqtrade/config_examples/config_my_hyperopt.json
# --strategy-path /freqtrade/templates
# --strategy TheForceV7
# --fee 0.0008

View File

@ -0,0 +1,230 @@
import numpy as np # noqa
import pandas as pd # noqa
from pandas import DataFrame
from freqtrade.strategy import IStrategy
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib
class TheForceV7V2(IStrategy):
INTERFACE_VERSION = 2
minimal_roi = {
"0": 10
}
stoploss = -0.1
trailing_stop = False
timeframe = '5m'
process_only_new_candles = False
use_sell_signal = True
sell_profit_only = False
ignore_roi_if_buy_signal = True
startup_candle_count: int = 30
order_types = {
'buy': 'limit',
'sell': 'limit',
'stoploss': 'market',
'stoploss_on_exchange': False
}
order_time_in_force = {
'buy': 'gtc',
'sell': 'gtc'
}
plot_config = {
'main_plot': {
'tema': {},
'sar': {'color': 'white'},
},
'subplots': {
"MACD": {
'macd': {'color': 'blue'},
'macdsignal': {'color': 'orange'},
},
"RSI": {
'rsi': {'color': 'red'},
}
}
}
def informative_pairs(self):
"""
Define additional, informative pair/interval combinations to be cached from the exchange.
These pair/interval combinations are non-tradeable, unless they are part
of the whitelist as well.
For more information, please consult the documentation
:return: List of tuples in the format (pair, interval)
Sample: return [("ETH/USDT", "5m"),
("BTC/USDT", "15m"),
]
"""
return []
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Adds several different TA indicators to the given DataFrame
Performance Note: For the best performance be frugal on the number of indicators
you are using. Let uncomment only the indicator you are using in your strategies
or your hyperopt configuration, otherwise you will waste your memory and CPU usage.
:param dataframe: Dataframe with data from the exchange
:param metadata: Additional information, like the currently traded pair
:return: a Dataframe with all mandatory indicators for the strategies
"""
stoch = ta.STOCH(dataframe)
dataframe['slowd'] = stoch['slowd']
dataframe['slowk'] = stoch['slowk']
dataframe['rsi7'] = ta.RSI(dataframe, timeperiod=7)
macd = ta.MACD(dataframe,12,26,1)
dataframe['macd'] = macd['macd']
dataframe['macdsignal'] = macd['macdsignal']
dataframe['macdhist'] = macd['macdhist']
dataframe['ema5h'] = ta.EMA(dataframe['high'], timeperiod=5)
dataframe['ema5l'] = ta.EMA(dataframe['low'], timeperiod=5)
dataframe['ema5c'] = ta.EMA(dataframe['close'], timeperiod=5)
dataframe['ema5o'] = ta.EMA(dataframe['open'], timeperiod=5)
dataframe['ema200c'] = ta.MA(dataframe['close'], 200)
dataframe['volvar'] = (dataframe['volume'].rolling(100).mean() * 1.5)
bollinger = qtpylib.bollinger_bands(dataframe['close'], window=21, stds=2)
dataframe['bb_lowerband'] = bollinger['lower']
dataframe['bb_upperband'] = bollinger['upper']
dataframe['bb_middleband'] = bollinger['mid']
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Based on TA indicators, populates the buy signal for the given dataframe
:param dataframe: DataFrame populated with indicators
:param metadata: Additional information, like the currently traded pair
:return: DataFrame with buy column
"""
dataframe.loc[
(
(
(
( #Original buy condition
(dataframe['slowk'] >= 20) & (dataframe['slowk'] <= 80)
&
(dataframe['slowd'] >= 20) & (dataframe['slowd'] <= 80)
)
|
( #V3 added based on SmoothScalp
(dataframe['slowk'] < 30) & (dataframe['slowd'] < 30) &
(qtpylib.crossed_above(dataframe['slowk'], dataframe['slowd']))
)
)
&
( #Original buy condition #Might need improvement to have better signals
(dataframe['macd'] > dataframe['macd'].shift(1))
&
(dataframe['macdsignal'] > dataframe['macdsignal'].shift(1))
)
&
( #Original buy condition
(dataframe['close'] > dataframe['close'].shift(1))
& #V6 added condition to improve buy's
(dataframe['open'] > dataframe['open'].shift(1))
)
&
( #Original buy condition
(dataframe['ema5c'] >= dataframe['ema5o'])
|
(dataframe['open'] < dataframe['ema5l'])
)
&
(
(dataframe['volume'] > dataframe['volvar'])
)
)
|
( # V2 Added buy condition w/ Bollingers bands
(dataframe['slowk'] >= 20) & (dataframe['slowk'] <= 80)
&
(dataframe['slowd'] >= 20) & (dataframe['slowd'] <= 80)
&
(
(dataframe['close'] <= dataframe['bb_lowerband'])
|
(dataframe['open'] <= dataframe['bb_lowerband'])
)
)
|
( # V5 added Pullback RSI thanks to simoelmou
(dataframe['close'] > dataframe['ema200c'])
&
(dataframe['rsi7'] < 35)
)
),
'buy'] = 1
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Based on TA indicators, populates the sell signal for the given dataframe
:param dataframe: DataFrame populated with indicators
:param metadata: Additional information, like the currently traded pair
:return: DataFrame with buy column
"""
dataframe.loc[
(
(
(
( #Original sell condition
(dataframe['slowk'] <= 80) & (dataframe['slowd'] <= 80)
)
|
( #V3 added based on SmoothScalp
(qtpylib.crossed_above(dataframe['slowk'], 70))
|
(qtpylib.crossed_above(dataframe['slowd'], 70))
)
)
&
( #Original sell condition
(dataframe['macd'] < dataframe['macd'].shift(1))
&
(dataframe['macdsignal'] < dataframe['macdsignal'].shift(1))
)
&
( #Original sell condition
(dataframe['ema5c'] < dataframe['ema5o'])
|
(dataframe['open'] >= dataframe['ema5h']) # V3 added based on SmoothScalp
)
)
|
( # V2 Added sell condition w/ Bollingers bands
(dataframe['slowk'] <= 80)
&
(dataframe['slowd'] <= 80)
&
(
(dataframe['close'] >= dataframe['bb_upperband'])
|
(dataframe['open'] >= dataframe['bb_upperband'])
)
)
|
(# V6 Added sell condition for extra high values
(dataframe['high'] > dataframe['bb_upperband'])
&
(((dataframe['high'] - dataframe['bb_upperband']) * 100 / dataframe['bb_upperband']) > 1)
)
),
'sell'] = 1
return dataframe

View File

@ -15,7 +15,7 @@ class TheForceV7(IStrategy):
stoploss = -0.1
trailing_stop = False
timeframe = '5m'
process_only_new_candles = False
process_only_new_candles = True
use_exit_signal = True # 替换 use_sell_signal
ignore_roi_if_entry_signal = True # 替换 ignore_roi_if_buy_signal
startup_candle_count: int = 30

10967
output.log

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"TheForceV7":{"run_id":"fb919d67e6fbce2435c96c8c47cff2fab275dca5","backtest_start_time":1747037695,"timeframe":"5m","timeframe_detail":null,"backtest_start_ts":1704067200,"backtest_end_ts":1744502400}}

View File

@ -0,0 +1,187 @@
from freqtrade.strategy import IStrategy
from pandas import DataFrame
import numpy as np # noqa
import pandas as pd # noqa
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib
class TheForceV7(IStrategy):
INTERFACE_VERSION = 3 # 升级到 V3 接口
minimal_roi = {
"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
startup_candle_count: int = 30
order_types = {
'entry': 'limit', # 替换 buy
'exit': 'limit', # 替换 sell
'stoploss': 'market',
'stoploss_on_exchange': False
}
order_time_in_force = {
'entry': 'gtc',
'exit': 'gtc'
}
plot_config = {
'main_plot': {
'tema': {},
'sar': {'color': 'white'},
},
'subplots': {
"MACD": {
'macd': {'color': 'blue'},
'macdsignal': {'color': 'orange'},
},
"RSI": {
'rsi': {'color': 'red'},
}
}
}
def informative_pairs(self):
return []
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
stoch = ta.STOCH(dataframe)
dataframe['slowd'] = stoch['slowd']
dataframe['slowk'] = stoch['slowk']
dataframe['rsi7'] = ta.RSI(dataframe, timeperiod=7)
macd = ta.MACD(dataframe, 12, 26, 1)
dataframe['macd'] = macd['macd']
dataframe['macdsignal'] = macd['macdsignal']
dataframe['macdhist'] = macd['macdhist']
dataframe['ema5h'] = ta.EMA(dataframe['high'], timeperiod=5)
dataframe['ema5l'] = ta.EMA(dataframe['low'], timeperiod=5)
dataframe['ema5c'] = ta.EMA(dataframe['close'], timeperiod=5)
dataframe['ema5o'] = ta.EMA(dataframe['open'], timeperiod=5)
dataframe['ema200c'] = ta.MA(dataframe['close'], 200)
dataframe['volvar'] = (dataframe['volume'].rolling(100).mean() * 1.5)
bollinger = qtpylib.bollinger_bands(dataframe['close'], window=21, stds=2)
dataframe['bb_lowerband'] = bollinger['lower']
dataframe['bb_upperband'] = bollinger['upper']
dataframe['bb_middleband'] = bollinger['mid']
return dataframe
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['ema5c'] >= dataframe['ema5o'])
|
(dataframe['open'] < dataframe['ema5l'])
)
&
(
(dataframe['volume'] > dataframe['volvar'])
)
|
(
(dataframe['slowk'] >= 20) & (dataframe['slowk'] <= 80)
&
(dataframe['slowd'] >= 20) & (dataframe['slowd'] <= 80)
&
(
(dataframe['close'] <= dataframe['bb_lowerband'])
|
(dataframe['open'] <= dataframe['bb_lowerband'])
)
)
|
(
(dataframe['close'] > dataframe['ema200c'])
&
(dataframe['rsi7'] < 35)
)
),
'enter_long'] = 1
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[
(
(
(
(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['slowk'] <= 80)
&
(dataframe['slowd'] <= 80)
&
(
(dataframe['close'] >= dataframe['bb_upperband'])
|
(dataframe['open'] >= dataframe['bb_upperband'])
)
)
|
(
(dataframe['high'] > dataframe['bb_upperband'])
&
(((dataframe['high'] - dataframe['bb_upperband']) * 100 / dataframe['bb_upperband']) > 1)
)
),
'exit_long'] = 1
return dataframe

View File

@ -0,0 +1 @@
{"$schema":"https://schema.freqtrade.io/schema.json","trading_mode":"spot","margin_mode":"isolated","max_open_trades":4,"stake_currency":"USDT","stake_amount":150,"startup_candle_count":30,"tradable_balance_ratio":1,"fiat_display_currency":"USD","dry_run":true,"identifier":"demo1","timeframe":"5m","dry_run_wallet":1000,"cancel_open_orders_on_exit":true,"stoploss":-0.05,"unfilledtimeout":{"entry":5,"exit":15},"exchange":{"name":"okx","key":"REDACTED","secret":"REDACTED","enable_ws":false,"ccxt_config":{"enableRateLimit":true,"rateLimit":500,"options":{"defaultType":"spot"}},"ccxt_async_config":{"enableRateLimit":true,"rateLimit":500,"timeout":20000},"pair_whitelist":["OKB/USDT","BTC/USDT","SOL/USDT","DOT/USDT","TON/USDT","ETH/USDT"],"pair_blacklist":[]},"freqai":{"enabled":true,"identifier":"test175","freqaimodel":"XGBoostRegressor","model_path":"/freqtrade/user_data/models","save_backtesting_prediction":true,"save_backtest_models":true,"backtest_period_days":10,"purge_old_models":true,"load_trained_model":true,"train_period_days":90,"live_retrain_hours":0,"include_predictions_in_final_dataframe":true,"data_kitchen":{"fillna":"ffill","feature_parameters":{"DI_threshold":0.5,"weight_factor":0.9}},"feature_parameters":{"include_timeframes":["5m","15m","1h"],"include_corr_pairlist":["BTC/USDT","ETH/USDT"],"label_period_candles":12,"include_shifted_candles":3,"indicator_periods_candles":[10,20,50],"plot_feature_importances":1,"feature_selection":{"method":"none"}},"data_split_parameters":{"test_size":0.2,"shuffle":false},"model_training_parameters":{"n_estimators":200,"learning_rate":0.05,"max_depth":6,"subsample":0.8,"colsample_bytree":0.8}},"entry_pricing":{"price_side":"same","use_order_book":true,"order_book_top":1,"price_last_balance":0.0,"check_depth_of_market":{"enabled":false,"bids_to_ask_delta":1}},"exit_pricing":{"price_side":"other","use_order_book":true,"order_book_top":1},"pairlists":[{"method":"StaticPairList"}],"api_server":{"enabled":true,"listen_ip_address":"0.0.0.0","listen_port":8080,"verbosity":"error","enable_openapi":false,"jwt_secret_key":"6a599ab046dbb419014807dffd7b8823bfa7e5df56b17d545485deb87331b4ca","ws_token":"6O5pBDiRigiZrmIsofaE2rkKMJtf9h8zVQ","CORS_origins":[],"username":"freqAdmin","password":"REDACTED"},"use_exit_signal":true,"bot_name":"freqtrade","initial_state":"running","force_entry_enable":false,"internals":{"process_throttle_secs":5,"heartbeat_interval":20,"loglevel":"DEBUG"},"config_files":["/freqtrade/config_examples/config_my_hyperopt.json"]}