2025-08-22 10:48:59 +00:00
|
|
|
|
import core.logger as logging
|
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
|
from time import sleep
|
|
|
|
|
|
import pandas as pd
|
2025-10-09 03:29:00 +00:00
|
|
|
|
import os
|
2025-08-22 10:48:59 +00:00
|
|
|
|
from core.biz.market_data import MarketData
|
|
|
|
|
|
from core.trade.ma_break_statistics import MaBreakStatistics
|
|
|
|
|
|
from core.db.db_market_data import DBMarketData
|
|
|
|
|
|
from core.biz.metrics_calculation import MetricsCalculation
|
|
|
|
|
|
from core.utils import (
|
|
|
|
|
|
datetime_to_timestamp,
|
|
|
|
|
|
timestamp_to_datetime,
|
|
|
|
|
|
transform_date_time_to_timestamp,
|
|
|
|
|
|
)
|
|
|
|
|
|
from trade_data_main import TradeDataMain
|
|
|
|
|
|
from config import (
|
|
|
|
|
|
API_KEY,
|
|
|
|
|
|
SECRET_KEY,
|
|
|
|
|
|
PASSPHRASE,
|
|
|
|
|
|
SANDBOX,
|
2025-08-31 03:20:59 +00:00
|
|
|
|
OKX_MONITOR_CONFIG,
|
2025-08-22 10:48:59 +00:00
|
|
|
|
BAR_THRESHOLD,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
logger = logging.logger
|
|
|
|
|
|
|
2025-09-17 11:33:37 +00:00
|
|
|
|
|
2025-08-22 10:48:59 +00:00
|
|
|
|
class TradeMaStrategyMain:
|
2025-09-17 11:33:37 +00:00
|
|
|
|
def __init__(
|
|
|
|
|
|
self,
|
|
|
|
|
|
is_us_stock: bool = False,
|
2025-09-25 04:28:43 +00:00
|
|
|
|
is_astock: bool = False,
|
|
|
|
|
|
is_aindex: bool = True,
|
2025-09-17 11:33:37 +00:00
|
|
|
|
is_binance: bool = False,
|
|
|
|
|
|
commission_per_share: float = 0,
|
2025-09-25 04:28:43 +00:00
|
|
|
|
buy_by_long_period: dict = {"by_week": False, "by_month": False},
|
2025-10-09 03:29:00 +00:00
|
|
|
|
long_period_condition: dict = {
|
|
|
|
|
|
"ma5>ma10": False,
|
|
|
|
|
|
"ma10>ma20": False,
|
|
|
|
|
|
"macd_diff>0": False,
|
|
|
|
|
|
"macd>0": False,
|
|
|
|
|
|
},
|
|
|
|
|
|
cut_loss_by_valleys_median: bool = False,
|
2025-09-17 11:33:37 +00:00
|
|
|
|
):
|
|
|
|
|
|
self.ma_break_statistics = MaBreakStatistics(
|
|
|
|
|
|
is_us_stock=is_us_stock,
|
2025-09-25 04:28:43 +00:00
|
|
|
|
is_astock=is_astock,
|
|
|
|
|
|
is_aindex=is_aindex,
|
2025-09-17 11:33:37 +00:00
|
|
|
|
is_binance=is_binance,
|
|
|
|
|
|
commission_per_share=commission_per_share,
|
2025-09-25 04:28:43 +00:00
|
|
|
|
buy_by_long_period=buy_by_long_period,
|
|
|
|
|
|
long_period_condition=long_period_condition,
|
2025-10-09 03:29:00 +00:00
|
|
|
|
cut_loss_by_valleys_median=cut_loss_by_valleys_median,
|
2025-09-17 11:33:37 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
2025-08-22 10:48:59 +00:00
|
|
|
|
def batch_ma_break_statistics(self):
|
|
|
|
|
|
"""
|
|
|
|
|
|
批量计算MA突破统计
|
|
|
|
|
|
"""
|
|
|
|
|
|
logger.info("开始批量计算MA突破统计")
|
|
|
|
|
|
strategy_dict = self.ma_break_statistics.main_strategy
|
2025-09-17 11:33:37 +00:00
|
|
|
|
account_value_chg_df_list = []
|
2025-08-22 10:48:59 +00:00
|
|
|
|
for strategy_name, strategy_info in strategy_dict.items():
|
2025-09-15 06:12:47 +00:00
|
|
|
|
if "macd" in strategy_name:
|
|
|
|
|
|
# 只计算macd策略
|
2025-09-17 11:33:37 +00:00
|
|
|
|
account_value_chg_df = self.ma_break_statistics.batch_statistics(
|
|
|
|
|
|
strategy_name=strategy_name
|
|
|
|
|
|
)
|
|
|
|
|
|
account_value_chg_df_list.append(account_value_chg_df)
|
|
|
|
|
|
|
|
|
|
|
|
total_account_value_chg_df = pd.concat(account_value_chg_df_list)
|
|
|
|
|
|
return total_account_value_chg_df
|
|
|
|
|
|
|
|
|
|
|
|
def statistics_account_value_chg(self, account_value_chg_df: pd.DataFrame):
|
|
|
|
|
|
logger.info("开始统计account_value_chg")
|
2025-08-23 17:44:33 +00:00
|
|
|
|
|
2025-08-22 10:48:59 +00:00
|
|
|
|
|
2025-09-25 04:28:43 +00:00
|
|
|
|
def test_single_symbol():
|
|
|
|
|
|
ma_break_statistics = MaBreakStatistics(
|
|
|
|
|
|
is_us_stock=False,
|
|
|
|
|
|
is_astock=True,
|
|
|
|
|
|
is_aindex=False,
|
|
|
|
|
|
is_binance=False,
|
|
|
|
|
|
commission_per_share=0,
|
|
|
|
|
|
)
|
|
|
|
|
|
symbol = "600111.SH"
|
|
|
|
|
|
bar = "1D"
|
2025-10-09 03:29:00 +00:00
|
|
|
|
ma_break_statistics.trade_simulate(
|
|
|
|
|
|
symbol=symbol, bar=bar, strategy_name="均线macd结合策略2"
|
|
|
|
|
|
)
|
2025-09-25 04:28:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
2025-10-09 03:29:00 +00:00
|
|
|
|
def batch_run_strategy():
|
2025-09-17 11:33:37 +00:00
|
|
|
|
commission_per_share_list = [0, 0.0008]
|
2025-10-09 03:29:00 +00:00
|
|
|
|
# cut_loss_by_valleys_median_list = [True, False]
|
|
|
|
|
|
cut_loss_by_valleys_median_list = [False]
|
|
|
|
|
|
buy_by_long_period_list = [
|
|
|
|
|
|
# {"by_week": True, "by_month": True, "buy_by_10_percentile": True},
|
|
|
|
|
|
{"by_week": False, "by_month": True, "buy_by_10_percentile": True},
|
|
|
|
|
|
{"by_week": True, "by_month": False, "buy_by_10_percentile": True},
|
|
|
|
|
|
{"by_week": False, "by_month": False, "buy_by_10_percentile": False},
|
|
|
|
|
|
]
|
|
|
|
|
|
# buy_by_long_period_list = [{"by_week": False, "by_month": False}]
|
|
|
|
|
|
long_period_condition_list = [
|
|
|
|
|
|
{"ma5>ma10": True, "ma10>ma20": True, "macd_diff>0": True, "macd>0": True},
|
|
|
|
|
|
{"ma5>ma10": True, "ma10>ma20": False, "macd_diff>0": True, "macd>0": True},
|
|
|
|
|
|
{"ma5>ma10": False, "ma10>ma20": True, "macd_diff>0": True, "macd>0": True},
|
|
|
|
|
|
]
|
|
|
|
|
|
|
2025-09-17 11:33:37 +00:00
|
|
|
|
for commission_per_share in commission_per_share_list:
|
2025-10-09 03:29:00 +00:00
|
|
|
|
for cut_loss_by_valleys_median in cut_loss_by_valleys_median_list:
|
|
|
|
|
|
for buy_by_long_period in buy_by_long_period_list:
|
|
|
|
|
|
for long_period_condition in long_period_condition_list:
|
|
|
|
|
|
logger.info(
|
|
|
|
|
|
f"开始计算, 主要参数:commission_per_share: {commission_per_share}, buy_by_long_period: {buy_by_long_period}, long_period_condition: {long_period_condition}"
|
|
|
|
|
|
)
|
|
|
|
|
|
trade_ma_strategy_main = TradeMaStrategyMain(
|
|
|
|
|
|
is_us_stock=False,
|
|
|
|
|
|
is_astock=False,
|
|
|
|
|
|
is_aindex=True,
|
|
|
|
|
|
is_binance=False,
|
|
|
|
|
|
commission_per_share=commission_per_share,
|
|
|
|
|
|
buy_by_long_period=buy_by_long_period,
|
|
|
|
|
|
long_period_condition=long_period_condition,
|
|
|
|
|
|
cut_loss_by_valleys_median=cut_loss_by_valleys_median,
|
|
|
|
|
|
)
|
|
|
|
|
|
trade_ma_strategy_main.batch_ma_break_statistics()
|
|
|
|
|
|
|
|
|
|
|
|
trade_ma_strategy_main = TradeMaStrategyMain(
|
|
|
|
|
|
is_us_stock=False,
|
|
|
|
|
|
is_astock=True,
|
|
|
|
|
|
is_aindex=False,
|
|
|
|
|
|
is_binance=False,
|
|
|
|
|
|
commission_per_share=commission_per_share,
|
|
|
|
|
|
buy_by_long_period=buy_by_long_period,
|
|
|
|
|
|
long_period_condition=long_period_condition,
|
|
|
|
|
|
cut_loss_by_valleys_median=cut_loss_by_valleys_median,
|
|
|
|
|
|
)
|
|
|
|
|
|
trade_ma_strategy_main.batch_ma_break_statistics()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def pickup_data_from_excel():
|
|
|
|
|
|
main_path = r"./output/trade_sandbox/ma_strategy"
|
|
|
|
|
|
sub_main_paths = ["aindex", "astock"]
|
|
|
|
|
|
fix_sub_path = "no_cut_loss_by_valleys_median"
|
|
|
|
|
|
sub_folder = r"excel/均线macd结合策略2/"
|
|
|
|
|
|
file_feature_name = "with_commission"
|
|
|
|
|
|
original_df_columns = [
|
|
|
|
|
|
"strategy_name",
|
|
|
|
|
|
"symbol",
|
|
|
|
|
|
"symbol_name",
|
|
|
|
|
|
"bar",
|
|
|
|
|
|
"total_buy_commission",
|
|
|
|
|
|
"total_sell_commission",
|
|
|
|
|
|
"total_commission",
|
|
|
|
|
|
"initial_account_value",
|
|
|
|
|
|
"final_account_value",
|
|
|
|
|
|
"account_value_chg",
|
|
|
|
|
|
"market_pct_chg",
|
|
|
|
|
|
]
|
|
|
|
|
|
original_df_list = []
|
|
|
|
|
|
for sub_main_path in sub_main_paths:
|
|
|
|
|
|
logger.info(f"开始读取{sub_main_path}数据")
|
|
|
|
|
|
full_sub_main_path = os.path.join(main_path, sub_main_path, fix_sub_path)
|
|
|
|
|
|
# 读取sub_main_path下的所有文件夹
|
|
|
|
|
|
folder_list = os.listdir(full_sub_main_path)
|
|
|
|
|
|
for folder in folder_list:
|
|
|
|
|
|
logger.info(f"开始读取{folder}数据")
|
|
|
|
|
|
folder_path = os.path.join(full_sub_main_path, folder)
|
|
|
|
|
|
properties = get_properties_by_folder_name(folder, sub_main_path)
|
|
|
|
|
|
logger.info(f"开始读取{folder}数据")
|
|
|
|
|
|
# 读取folder_path的sub_folder下的所有文件
|
|
|
|
|
|
sub_folder_path = os.path.join(folder_path, sub_folder)
|
|
|
|
|
|
file_list = os.listdir(sub_folder_path)
|
|
|
|
|
|
for file in file_list:
|
|
|
|
|
|
logger.info(f"开始读取{file}数据")
|
|
|
|
|
|
if file_feature_name in file:
|
|
|
|
|
|
file_path = os.path.join(sub_folder_path, file)
|
|
|
|
|
|
df = pd.read_excel(file_path, sheet_name="资产价值变化")
|
|
|
|
|
|
logger.info(f"开始读取{file}数据")
|
|
|
|
|
|
# 向df添加properties
|
|
|
|
|
|
df = df.assign(**properties)
|
|
|
|
|
|
df = df[list(properties.keys()) + original_df_columns]
|
|
|
|
|
|
# 将df添加到original_df_list
|
|
|
|
|
|
original_df_list.append(df)
|
|
|
|
|
|
final_df = pd.concat(original_df_list)
|
|
|
|
|
|
excel_folder_path = os.path.join(main_path, "aindex_astock_均线macd结合策略2")
|
|
|
|
|
|
os.makedirs(excel_folder_path, exist_ok=True)
|
|
|
|
|
|
excel_file_path = os.path.join(
|
|
|
|
|
|
excel_folder_path, "all_strategy_with_commission.xlsx"
|
|
|
|
|
|
)
|
|
|
|
|
|
with pd.ExcelWriter(excel_file_path) as writer:
|
|
|
|
|
|
final_df.to_excel(
|
|
|
|
|
|
writer, sheet_name="all_strategy_with_commission", index=False
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_properties_by_folder_name(folder_name: str, symbol_type: str):
|
|
|
|
|
|
properties = {}
|
|
|
|
|
|
sub_properties = folder_name.split("_")
|
|
|
|
|
|
properties["symbol_type"] = symbol_type
|
|
|
|
|
|
properties["buy_by_long_period"] = "no_long_period"
|
|
|
|
|
|
properties["long_period_ma5gtma10"] = False
|
|
|
|
|
|
properties["long_period_ma10gtma20"] = False
|
|
|
|
|
|
properties["long_period_macd_diffgt0"] = False
|
|
|
|
|
|
properties["long_period_macdgt0"] = False
|
|
|
|
|
|
properties["buy_by_long_period_10_percentile"] = False
|
|
|
|
|
|
if "1M" in sub_properties:
|
|
|
|
|
|
properties["buy_by_long_period"] = "1M"
|
|
|
|
|
|
if "1W" in sub_properties:
|
|
|
|
|
|
properties["buy_by_long_period"] = "1W"
|
|
|
|
|
|
if "1W1M" in sub_properties:
|
|
|
|
|
|
properties["buy_by_long_period"] = "1W1M"
|
|
|
|
|
|
if "ma5gtma10" in sub_properties:
|
|
|
|
|
|
properties["long_period_ma5gtma10"] = True
|
|
|
|
|
|
if "ma10gtma20" in sub_properties:
|
|
|
|
|
|
properties["long_period_ma10gtma20"] = True
|
|
|
|
|
|
if "macd_diffgt0" in sub_properties:
|
|
|
|
|
|
properties["long_period_macd_diffgt0"] = True
|
|
|
|
|
|
if "macdgt0" in sub_properties:
|
|
|
|
|
|
properties["long_period_macdgt0"] = True
|
|
|
|
|
|
if "10percentile" in sub_properties:
|
|
|
|
|
|
properties["buy_by_long_period_10_percentile"] = True
|
|
|
|
|
|
return properties
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def profit_loss_ratio():
|
|
|
|
|
|
"""
|
|
|
|
|
|
计算利润损失比
|
|
|
|
|
|
公式:盈利/盈利交易次数 : 亏损/亏损交易次数
|
|
|
|
|
|
"""
|
|
|
|
|
|
folder = r"./output/trade_sandbox/ma_strategy/binance/excel/均线macd结合策略2/"
|
|
|
|
|
|
prefix = ["无交易费用", "有交易费用"]
|
|
|
|
|
|
for prefix in prefix:
|
|
|
|
|
|
excel_file_path = os.path.join(
|
|
|
|
|
|
folder, f"{prefix}_趋势投资_from_201708181600_to_202509020600.xlsx"
|
|
|
|
|
|
)
|
|
|
|
|
|
df = pd.read_excel(excel_file_path, sheet_name="买卖记录明细")
|
|
|
|
|
|
symbol_list = list(df["symbol"].unique())
|
|
|
|
|
|
bar_list = list(df["bar"].unique())
|
|
|
|
|
|
data_list = []
|
|
|
|
|
|
for symbol in symbol_list:
|
|
|
|
|
|
for bar in bar_list:
|
|
|
|
|
|
df_symbol_bar = df[df["symbol"] == symbol][df["bar"] == bar]
|
|
|
|
|
|
start_date = df_symbol_bar["begin_date_time"].min()
|
|
|
|
|
|
end_date = df_symbol_bar["end_date_time"].max()
|
|
|
|
|
|
profit_df = df_symbol_bar[df_symbol_bar["profit_loss"] > 0]
|
|
|
|
|
|
loss_df = df_symbol_bar[df_symbol_bar["profit_loss"] < 0]
|
|
|
|
|
|
|
|
|
|
|
|
profit_amount = sum(profit_df["profit_loss"])
|
|
|
|
|
|
loss_amount = abs(sum(loss_df["profit_loss"]))
|
|
|
|
|
|
|
|
|
|
|
|
profit_count = len(profit_df)
|
|
|
|
|
|
loss_count = len(loss_df)
|
|
|
|
|
|
|
|
|
|
|
|
if profit_count == 0 or loss_count == 0:
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
|
profit_loss_ratio = round(
|
|
|
|
|
|
(profit_amount / profit_count) / (loss_amount / loss_count) * 100, 4
|
2025-09-25 04:28:43 +00:00
|
|
|
|
)
|
2025-10-09 03:29:00 +00:00
|
|
|
|
|
|
|
|
|
|
data_list.append(
|
|
|
|
|
|
{
|
|
|
|
|
|
"币种": symbol,
|
|
|
|
|
|
"交易周期": bar,
|
|
|
|
|
|
"开始时间": start_date,
|
|
|
|
|
|
"结束时间": end_date,
|
|
|
|
|
|
"盈利金额": profit_amount,
|
|
|
|
|
|
"盈利次数": profit_count,
|
|
|
|
|
|
"亏损金额": loss_amount,
|
|
|
|
|
|
"亏损次数": loss_count,
|
|
|
|
|
|
"盈亏比": profit_loss_ratio,
|
|
|
|
|
|
"盈亏比公式": f"盈利金额/盈利次数 : 亏损金额/亏损次数",
|
|
|
|
|
|
}
|
2025-09-25 04:28:43 +00:00
|
|
|
|
)
|
2025-10-09 03:29:00 +00:00
|
|
|
|
final_df = pd.DataFrame(data_list)
|
|
|
|
|
|
final_df.to_excel(os.path.join(folder, f"{prefix}时虚拟货币利润损失比.xlsx"), index=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
|
# batch_run_strategy()
|
|
|
|
|
|
profit_loss_ratio()
|