diff --git a/回测数据/analysis_results.xlsx b/回测数据/analysis_results.xlsx deleted file mode 100644 index 580d660..0000000 Binary files a/回测数据/analysis_results.xlsx and /dev/null differ diff --git a/回测数据/haha b/回测数据/haha deleted file mode 100644 index cc1e065..0000000 --- a/回测数据/haha +++ /dev/null @@ -1,134 +0,0 @@ -id amount amountConvert count open close low high vol -1756396740 62532 625.32 114 4501.26 4501.56 4500.03 4503.08 281496269.14 -1756396680 88506 885.06 148 4505.76 4501.19 4500.08 4505.76 398449047.46 -1756396620 203942 2039.42 246 4503.16 4505.78 4503.16 4508.22 918868972.64 -1756396560 228030 2280.30 236 4492.01 4503.41 4491.99 4504.13 1026263843.08 -1756396500 73404 734.04 131 4493.04 4492 4491.81 4497.62 329904043.75 -1756396440 96427 964.27 142 4494.78 4492.84 4490.95 4495.64 433262143.22 -1756396380 89492 894.92 169 4490.66 4494.39 4490.66 4495.61 402162647.95 -1756396320 85316 853.16 150 4489.73 4490.78 4487.9 4493.19 383029292.66 -1756396260 205406 2054.06 221 4484.97 4490.2 4484.3 4494.68 921942135.11 -1756396200 594583 5945.83 491 4491.52 4488.67 4482 4495.03 2668697992.17 -1756396140 1116890 11168.90 917 4509.02 4491.36 4482.86 4509.94 5016487489.16 - -数据是import datetime -import requests - -import pandas as pd - -headers = { - 'accept': 'application/json, text/plain, */*', - 'accept-language': 'zh,zh-CN;q=0.9,zh-HK;q=0.8,en;q=0.7', - 'cache-control': 'no-cache', - 'origin': 'https://www.websea.com', - 'pragma': 'no-cache', - 'priority': 'u=1, i', - 'referer': 'https://www.websea.com/', - 'sec-ch-ua': '"Chromium";v="140", "Not=A?Brand";v="24", "Google Chrome";v="140"', - 'sec-ch-ua-mobile': '?0', - 'sec-ch-ua-platform': '"Windows"', - 'sec-fetch-dest': 'empty', - 'sec-fetch-mode': 'cors', - 'sec-fetch-site': 'same-site', - 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36', -} - -if __name__ == '__main__': - datas = [] - - # 定义开始日期和结束日期 - time_ser = datetime.datetime(2025, 9, 25) - - # 获取当天开始时刻(00:00:00) - start_of_day = time_ser.replace(hour=0, minute=0, second=0, microsecond=0) - # 获取当天结束时刻(23:59:59) - end_of_day = time_ser.replace(hour=23, minute=59, second=59, microsecond=0) - - # 将开始时刻和结束时刻转换为时间戳 - start_timestamp = start_of_day.timestamp() - end_timestamp = end_of_day.timestamp() - - params = { - 'symbol': 'ETH-USDT', - 'period': '1min', - 'start': int(start_timestamp), - 'end': int(end_timestamp), - } - - response = requests.get('https://capi.websea.com/webApi/market/getKline', params=params, headers=headers) - - # 提取数据 - data = response.json()['result']['data'] - - # 根据 id 进行排序 - sorted_data = sorted(data, key=lambda x: x['id']) - - low_data = None - - n = 0 - n1 = 0 - for _, i in enumerate(sorted_data): - - if not low_data: - low_data = i - continue - - - # 当前一笔是多 - if i['open'] < i['close']: - - if low_data['open'] < low_data['close']: - - if float(i['open']) < float(low_data['open']) and float(i['close']) > float(low_data['close']): - - try: - if sorted_data[_ + 3]["open"] > i['open'] and sorted_data[_ + 3]["close"] > i['close']: - print(f"老数据:{low_data}") - print(f"老数据:{i}") - print(f"新数据:{sorted_data[_ + 3]}") - - print("做多" + "-" * 50) - except: - pass - - # if float(i['open']) < float(low_data['open']) and float(i['close']) < float(low_data['close']): - # - # try: - # if sorted_data[_ + 3]["open"] < i['open'] and sorted_data[_ + 3]["close"] < i['close']: - # print(f"老数据:{i}") - # print(f"新数据:{sorted_data[_ + 3]}") - # - # print("做空" + "-" * 50) - # except: - # pass - - low_data = i - - print(n) - - -这样获取的, - - -这样的数据,我需要解析开盘价格和结束价格,open就是开盘价格,close就是结束价格,然后id是时间戳,我需要对比, -# 第一种情况:当前一笔是涨的,这里又有两种情况。第一种情况:前一笔是涨的,当前一笔的价格,开盘的价格小于前一笔,结盘的价格大于前一笔;第二种情况:前一笔是跌的,当前一笔的开盘价格低于前一笔的结盘价格,当前一笔的结盘价格大于前一笔的开盘价格, -# 第二种情况:当前一笔是跌的,这里又有两种情况。第一种情况:前一笔是跌的,当前一笔的价格,开盘的价格大于前一笔,结盘的价格小于前一笔;第二种情况,前一笔是涨的,当前一笔的开盘价格大于前一笔的结盘价格,当前价格的结盘价格小于前一笔的开盘价格, - -然后我需要预测出胜率,当前一笔是涨的,两笔后的结算价格大于当前一笔的结算价格,就是赚, -当前一笔是跌的,两笔后的结算价格小于当前一笔的结算价格,就是赚, - -这样就是当前价格从k线图中看,就是前一笔的开盘价和结盘价处于当前一笔的开盘价和结盘价中间包裹住的情况,然后需要查询出来 - - -# 第一种情况:当前一笔是涨的,前一笔是跌的,当前一笔的开盘价格低于前一笔的结盘价格,当前一笔的结盘价格大于前一笔的开盘价格, -# 第二种情况:当前一笔是跌的,前一笔是涨的,当前一笔的开盘价格大于前一笔的结盘价格,当前价格的结盘价格小于前一笔的开盘价格, - - -ui:8000 -前端:15000 -一次性, - - - - - diff --git a/回测数据/kline_data.xlsx b/回测数据/kline_data.xlsx deleted file mode 100644 index e77ddf2..0000000 Binary files a/回测数据/kline_data.xlsx and /dev/null differ diff --git a/回测数据/main.py b/回测数据/main.py deleted file mode 100644 index 5bd4dda..0000000 --- a/回测数据/main.py +++ /dev/null @@ -1,39 +0,0 @@ -import pandas as pd - -if __name__ == '__main__': - - # 读取 Excel 文件 - file_path = 'kline_data.xlsx' - df = pd.read_excel(file_path, ) - - # 逐行读取数据 - ls = {} - for index, row in df.iterrows(): - # print(row) - - id = row['id'] - open = row['open'] - close = row['close'] - - - - # ls[str(int(id))] = {'open': float(open), 'close': float(close)} - - # # 根据键进行排序 - # sorted_data = dict(sorted(ls.items())) - # - # low_data = None - # new_data = None - # for _, i in enumerate(sorted_data): - # if _: - # - # # 跳过第一个 - # if not low_data: - # low_data = i - # - # continue - # - # if sorted_data[i]["open"] > low_data[low_data]["open"]: - # if sorted_data[i]["close"] > low_data[low_data]["close"]: - # print(low_data) - # print(i) diff --git a/回测数据/test.py b/回测数据/test.py deleted file mode 100644 index ec0f876..0000000 --- a/回测数据/test.py +++ /dev/null @@ -1,6 +0,0 @@ -print(10000 * 0.0005) -print(10000 * 0.001) - -print(40) - -print(100 + 350 - (2120 * 0.1) + (2120 * 0.9)) diff --git a/回测数据/test1.py b/回测数据/test1.py deleted file mode 100644 index e05c5d3..0000000 --- a/回测数据/test1.py +++ /dev/null @@ -1,138 +0,0 @@ -import datetime -import requests -from loguru import logger - -headers = { - 'accept': 'application/json, text/plain, */*', - 'accept-language': 'zh,zh-CN;q=0.9,zh-HK;q=0.8,en;q=0.7', - 'cache-control': 'no-cache', - 'origin': 'https://www.websea.com', - 'pragma': 'no-cache', - 'priority': 'u=1, i', - 'referer': 'https://www.websea.com/', - 'sec-ch-ua': '"Chromium";v="140", "Not=A?Brand";v="24", "Google Chrome";v="140"', - 'sec-ch-ua-mobile': '?0', - 'sec-ch-ua-platform': '"Windows"', - 'sec-fetch-dest': 'empty', - 'sec-fetch-mode': 'cors', - 'sec-fetch-site': 'same-site', - 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36', -} - -if __name__ == '__main__': - - zh_project = 0 - all_trades = [] # 存放所有交易记录 - - for i in range(1, 29): - - # 请求数据 - time_ser = datetime.datetime(2025, 9, i) - start_of_day = time_ser.replace(hour=0, minute=0, second=0, microsecond=0) - end_of_day = time_ser.replace(hour=23, minute=59, second=59, microsecond=0) - params = { - 'symbol': 'ETH-USDT', - 'period': '1min', - 'start': int(start_of_day.timestamp()), - 'end': int(end_of_day.timestamp()), - } - - response = requests.get('https://capi.websea.com/webApi/market/getKline', params=params, headers=headers) - data = response.json()['result']['data'] - sorted_data = sorted(data, key=lambda x: x['id']) - - signals = 0 - wins = 0 - - lig_price = 0 - low_price = 0 - - for idx in range(1, len(sorted_data) - 5): # 需要至少留两根K线做验证 - prev = sorted_data[idx - 1] # 前一笔 - curr = sorted_data[idx] # 当前这笔 - future = sorted_data[idx + 5] # 两根后的K线 - - prev_open, prev_close = float(prev['open']), float(prev['close']) - curr_open, curr_close = float(curr['open']), float(curr['close']) - future_close = float(future['close']) - - # 当前为涨 - if curr_close > curr_open: - # 前一笔涨 + 包裹 - if prev_close > prev_open and curr_open < prev_open and curr_close > prev_close: - signals += 1 - diff = future_close - curr_close - lig_price += diff - all_trades.append((f"{i}号", curr["id"], "做多", curr_close, future_close, diff, future["id"])) - - if future_close > curr_close: - wins += 1 - - # 前一笔跌 + 反包 - elif prev_close < prev_open and curr_open < prev_close and curr_close > prev_open: - signals += 1 - diff = future_close - curr_close - lig_price += diff - all_trades.append((f"{i}号", curr["id"], "做多", curr_close, future_close, diff, future["id"])) - - if future_close > curr_close: - wins += 1 - - # 当前为跌 - elif curr_close < curr_open: - # 前一笔跌 + 包裹 - if prev_close < prev_open and curr_open > prev_open and curr_close < prev_close: - signals += 1 - diff = curr_close - future_close - low_price += diff - all_trades.append((f"{i}号", curr["id"], "做空", curr_close, future_close, diff, future["id"])) - - if future_close < curr_close: - wins += 1 - - # 前一笔涨 + 反包 - elif prev_close > prev_open and curr_open > prev_close and curr_close < prev_open: - signals += 1 - diff = curr_close - future_close - low_price += diff - all_trades.append((f"{i}号", curr["id"], "做空", curr_close, future_close, diff, future["id"])) - - if future_close < curr_close: - wins += 1 - - if signals > 0: - logger.info( - f"日期:{i}号,信号数={signals}, 胜率={wins / signals * 100:.2f}%,上涨方向:{lig_price:.2f},下跌方向:{low_price:.2f},综合价格:{(lig_price + low_price):.2f}" - ) - else: - logger.info(f"日期:{i}号,没有信号") - - zh_project += (lig_price + low_price) - - logger.success(f"综合价格:{zh_project:.2f}") - - # 输出每笔交易 - logger.info("===== 每笔交易详情 =====") - - n = 0 - n1 = 0 - for trade in all_trades: - date, time_str, direction, entry, exit, diff, end_time = trade - - # logger.info(f"{date} {direction} 入场={entry:.2f} 出场={exit:.2f} 差价={diff:.2f} 盈利:{diff / entry * 10000}") - logger.info( - f"{date} {time_str} {direction} 入场={entry:.2f} 出场={exit:.2f} 出场时间:{end_time} 差价={diff:.2f} 盈利:{diff / entry * 10000} 开仓手续费:5u 平仓手续费:{10000 / entry * exit * 0.0005}" - ) - - # 手续费率是在 0.06% - # 开仓手续费 - # 平仓手续费 - # 10000 / entry * exit * 0.0006 - - n1 += 5 + (10000 / entry * exit * 0.0005) - - n += ((diff / entry) * 10000) - - print(len(all_trades)) - print(n) - print(n1) diff --git a/回测数据/test2.py b/回测数据/test2.py index cbb746e..988e198 100644 --- a/回测数据/test2.py +++ b/回测数据/test2.py @@ -24,7 +24,7 @@ headers = { def fetch_kline(day: int): """获取某一天的分钟级 K线数据""" # 构造该日的起止时间戳 - time_ser = datetime.datetime(2025, 9, day) + time_ser = datetime.datetime(2025, 6, day) start_of_day = time_ser.replace(hour=0, minute=0, second=0, microsecond=0) end_of_day = time_ser.replace(hour=23, minute=59, second=59, microsecond=0) params = { diff --git a/回测数据/推测策略,回测.py b/回测数据/推测策略,回测.py index 0156282..8bb20d7 100644 --- a/回测数据/推测策略,回测.py +++ b/回测数据/推测策略,回测.py @@ -2,6 +2,7 @@ import datetime import requests from loguru import logger +# 请求头,用于伪装成浏览器访问接口 headers = { 'accept': 'application/json, text/plain, */*', 'accept-language': 'zh,zh-CN;q=0.9,zh-HK;q=0.8,en;q=0.7', @@ -21,125 +22,159 @@ headers = { def fetch_kline(day: int): - """获取某一天的分钟K线数据""" - time_ser = datetime.datetime(2025, 9, day) + """获取某一天的分钟级 K线数据""" + # 构造该日的起止时间戳 + time_ser = datetime.datetime(2025, 9, day) # 修正为2024年9月 start_of_day = time_ser.replace(hour=0, minute=0, second=0, microsecond=0) end_of_day = time_ser.replace(hour=23, minute=59, second=59, microsecond=0) params = { - 'symbol': 'ETH-USDT', - 'period': '1min', - 'start': int(start_of_day.timestamp()), - 'end': int(end_of_day.timestamp()), + 'symbol': 'ETH-USDT', # 交易对 + 'period': '1min', # 分钟级K线 + 'start': int(start_of_day.timestamp()), # 开始时间 + 'end': int(end_of_day.timestamp()), # 结束时间 } + # 请求 API 获取数据 response = requests.get('https://capi.websea.com/webApi/market/getKline', params=params, headers=headers) data = response.json()['result']['data'] + # 按 id 排序(保证时间顺序) return sorted(data, key=lambda x: x['id']) +# ================= 辅助函数 ================= + +def is_bullish(candle): + """判断是否是阳线(收盘价 > 开盘价)""" + return float(candle['close']) > float(candle['open']) + + +def is_bearish(candle): + """判断是否是阴线(收盘价 < 开盘价)""" + return float(candle['close']) < float(candle['open']) + + +def check_signal(prev, curr): + """ + 判断是否出现反包形态: + 1. 前一根阴线,后一根阳线,并且阳线包住前一根阴线 -> 做多信号 + 2. 前一根阳线,后一根阴线,并且阴线包住前一根阳线 -> 做空信号 + """ + p_open, p_close = float(prev['open']), float(prev['close']) + c_open, c_close = float(curr['open']), float(curr['close']) + + # 情况1:前阴后阳,且阳线包住前阴 + if is_bullish(curr) and is_bearish(prev): + if c_open < p_close and c_close > p_open: + return "long" + + # 情况2:前阳后阴,且阴线包住前阳 + if is_bearish(curr) and is_bullish(prev): + if c_open > p_close and c_close < p_open: + return "short" + + return None + + +def simulate_trade(direction, entry_price, future_candles, take_profit_diff=5, stop_loss_diff=-2): + """ + 模拟交易(逐根K线回测) + 使用价差来控制止盈止损: + - 盈利达到 take_profit_diff 就止盈 + - 亏损达到 stop_loss_diff 就止损 + """ + + for candle in future_candles: + high, low, close = float(candle['high']), float(candle['low']), float(candle['close']) + + if direction == "long": + # 做多:检查最高价是否达到止盈,最低价是否触及止损 + if high >= entry_price + take_profit_diff: + return entry_price + take_profit_diff, take_profit_diff, candle['id'] # 止盈 + if low <= entry_price + stop_loss_diff: + return entry_price + stop_loss_diff, stop_loss_diff, candle['id'] # 止损 + + elif direction == "short": + # 做空:检查最低价是否达到止盈,最高价是否触及止损 + if low <= entry_price - take_profit_diff: + return entry_price - take_profit_diff, take_profit_diff, candle['id'] # 止盈 + if high >= entry_price - stop_loss_diff: + return entry_price - stop_loss_diff, stop_loss_diff, candle['id'] # 止损 + + # 如果未来都没触发,最后一根收盘平仓 + final_price = float(future_candles[-1]['close']) + if direction == "long": + diff_money = final_price - entry_price + else: + diff_money = entry_price - final_price + + return final_price, diff_money, future_candles[-1]['id'] + + +# ================= 主程序 ================= if __name__ == '__main__': + zh_project = 0 # 累计盈亏 + all_trades = [] # 保存所有交易明细 - zh_project = 0 - all_trades = [] # 存放所有交易记录 + # 遍历 9月1日 ~ 9月27日 + for i in range(1, 30): + sorted_data = fetch_kline(i) # 获取数据 - for i in range(27, 28): - - sorted_data = fetch_kline(i) # 获取交易数据 - - # 信号数 盈利的笔数 signals = wins = 0 - # 涨方向盈利多少 跌方向盈利多少 - lig_price = low_price = 0 + lig_price = low_price = 0 # 分别记录多/空的净收益 - for idx in range(1, len(sorted_data) - 4): - prev = sorted_data[idx - 1] # 前一根K - curr = sorted_data[idx] # 当前K - entry_candle = sorted_data[idx + 1] # ✅ 下一根K线作为开仓点 - future = sorted_data[idx + 4] # 5根后的K线 + # 遍历每根K线,寻找信号 + for idx in range(1, len(sorted_data) - 2): # 留出未来K线 + prev, curr = sorted_data[idx - 1], sorted_data[idx] # 前一笔,当前一笔 + entry_candle = sorted_data[idx + 1] # 下一根开盘价作为入场价 + future_candles = sorted_data[idx + 2:] # 未来行情 - prev_open, prev_close = float(prev['open']), float(prev['close']) # 前一笔开盘,前一笔结盘 - curr_open, curr_close = float(curr['open']), float(curr['close']) # 当前一笔开盘,当前一笔结盘 - entry_open = float(entry_candle['open']) # 下一笔开仓 - future_close = float(future['close']) # 四根后结盘 + entry_open = float(entry_candle['open']) # 开仓价格 + direction = check_signal(prev, curr) # 判断开仓方向 - # 当前为涨 - if curr_close > curr_open: - # 前一笔涨 + 包裹 + if direction: + signals += 1 # 总共信号数 + exit_price, diff, exit_time = simulate_trade(direction, entry_open, future_candles) - if prev_close > prev_open and curr_open < prev_open and curr_close > prev_close: - future = sorted_data[idx + 7] - future_close = float(future['close']) # 四根后结盘 - - - signals += 1 - diff = future_close - entry_open + # 统计多单/空单盈亏情况 + if direction == "long": lig_price += diff + if diff > 0: wins += 1 + else: + low_price += diff + if diff > 0: wins += 1 - if future_close > entry_open: - wins += 1 - - all_trades.append( - (f"{i}号", entry_candle["id"], "做多", entry_open, future_close, diff, future["id"])) - - - - # # 前一笔跌 + 反包 - # elif prev_close < prev_open and curr_open < prev_close and curr_close > prev_open: - # signals += 1 - # diff = future_close - entry_open - # lig_price += diff - # all_trades.append((f"{i}号", entry_candle["id"], "做多", entry_open, future_close, diff, future["id"])) - # - # if future_close > entry_open: - # wins += 1 - # - # # 当前为跌 - # elif curr_close < curr_open: - # # 前一笔跌 + 包裹 - # if prev_close < prev_open and curr_open > prev_open and curr_close < prev_close: - # signals += 1 - # diff = entry_open - future_close - # low_price += diff - # all_trades.append((f"{i}号", entry_candle["id"], "做空", entry_open, future_close, diff, future["id"])) - # - # if future_close < entry_open: - # wins += 1 - # - # # 前一笔涨 + 反包 - # elif prev_close > prev_open and curr_open > prev_close and curr_close < prev_open: - # signals += 1 - # diff = entry_open - future_close - # low_price += diff - # all_trades.append((f"{i}号", entry_candle["id"], "做空", entry_open, future_close, diff, future["id"])) - # - # if future_close < entry_open: - # wins += 1 + # 保存交易详情 + all_trades.append((f"{i}号", entry_candle["id"], "做多" if direction == "long" else "做空", + entry_open, exit_price, diff, exit_time)) + # 输出每日统计结果 if signals > 0: logger.info( - f"日期:{i}号,信号数={signals}, 胜率={wins / signals * 100:.2f}%,上涨方向:{lig_price:.2f},下跌方向:{low_price:.2f},综合价格:{(lig_price + low_price):.2f}" + f"日期:{i}号,信号数={signals}, 胜率={wins / signals * 100:.2f}%," + f"上涨方向={lig_price:.2f},下跌方向={low_price:.2f},综合={lig_price + low_price:.2f}" ) else: logger.info(f"日期:{i}号,没有信号") + # 累计盈亏 zh_project += (lig_price + low_price) logger.success(f"综合价格:{zh_project:.2f}") - # 输出每笔交易 + # ===== 输出每笔交易详情 ===== logger.info("===== 每笔交易详情 =====") - - n = n1 = 0 - for trade in all_trades: - date, time_str, direction, entry, exit, diff, end_time = trade + n = n1 = 0 # n = 总盈利,n1 = 总手续费 + for date, time_str, direction, entry, exit, diff, end_time in all_trades: + profit_amount = diff / entry * 10000 # 计算盈利金额 + close_fee = 10000 / entry * exit * 0.0005 # 平仓手续费 logger.info( - f"{date} {time_str} {direction} 入场={entry:.2f} 出场={exit:.2f} 出场时间:{end_time} 差价={diff:.2f} 盈利:{diff / entry * 10000} " - f"开仓手续费:5u 平仓手续费:{10000 / entry * exit * 0.0005}" + f"{date} {time_str} {direction} 入场={entry:.2f} 出场={exit:.2f} 出场时间={end_time} " + f"差价={diff:.2f} 盈利={profit_amount:.2f} " + f"开仓手续费=5u 平仓手续费={close_fee:.2f}" ) - - n1 += 5 + (10000 / entry * exit * 0.0005) - n += (diff / entry) * 10000 + n1 += 5 + close_fee + n += profit_amount print(f'一共笔数:{len(all_trades)}') - print(f"一共盈利:{n}") - print(f'一共手续费:{n1}') + print(f"一共盈利:{n:.2f}") + print(f'一共手续费:{n1:.2f}')