From cef8945fe8839e011c3daf64a0833f069d1e7062 Mon Sep 17 00:00:00 2001 From: Zichao Lin Date: Sat, 19 Jul 2025 20:50:55 +0800 Subject: [PATCH] feat(csv): record filled trade to csv Closes #3 --- main.py | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 3 deletions(-) diff --git a/main.py b/main.py index 2c105b9..649b15c 100644 --- a/main.py +++ b/main.py @@ -1,6 +1,8 @@ +import csv +from datetime import datetime import time import logging -from typing import Dict, List, Optional, Tuple +from typing import Any, Dict, List, Optional, Tuple from dataclasses import dataclass import mexc_spot_v3 @@ -49,6 +51,8 @@ class GridTradingBot: 参数: conf (Dict): 配置字典,包含: - symbol: 交易对 (如 'BTCUSDC') + - csv_symbol: CSV中映射的交易对 (如 'BTCUSDT') + - csv_file: CSV记录文件 (如 'output/mexc-spot-grid-trades.csv') - grid_percentage: 每格百分比 (如 0.005 表示 0.5%) - grid_count: 单边网格数量 (如 3) - order_amount: 每单加密货币数量 (如 0.00001 BTC) @@ -62,6 +66,8 @@ class GridTradingBot: ) self.config = conf self.symbol = conf["symbol"] + self.csv_symbol = conf["csv_symbol"] + self.csv_file = conf["csv_file"] self.grid_percentage = conf["grid_percentage"] self.grid_count = conf["grid_count"] self.order_amount = conf["order_amount"] @@ -85,6 +91,78 @@ class GridTradingBot: self.running = False logger.info("[GridTradingBot.__init__] GridTradingBot initialized successfully") + def record_transaction(self, order_response: Dict[str, Any]) -> bool: + """ + 记录交易到CSV文件 + + Args: + order_data: 订单数据字典 + + Returns: + 是否成功记录 + """ + + try: + csv_symbol = self.csv_symbol + order_id = order_response["orderId"] + executed_qty = order_response["executedQty"] + cummulative_quote_qty = order_response["cummulativeQuoteQty"] + side = order_response["side"] + trade_type = "买入" if side == "BUY" else "卖出" + + timestamp = datetime.fromtimestamp(order_response["updateTime"] / 1000).strftime( + "%Y-%m-%dT%H:%M" + ) + + row = [ + timestamp, + trade_type, + csv_symbol, + executed_qty, + cummulative_quote_qty, + "资金账户", + "CEX", + f"MEXC API - Order ID: {order_id}", + ] + + # 检查文件是否存在 + file_exists = False + try: + with open(self.csv_file, "r", encoding="utf-8") as f: + file_exists = True + except FileNotFoundError: + pass + + # 写入CSV + with open(self.csv_file, "a", newline="", encoding="utf-8") as f: + writer = csv.writer(f) + if not file_exists: + writer.writerow( + [ + "日期", + "类型", + "证券代码", + "份额", + "净额", + "现金账户", + "目标账户", + "备注", + ] + ) + writer.writerow(row) + + logger.info( + "[GridTradingBot.record_transaction] Transaction recorded, order ID: %s", + order_id, + ) + return True + except Exception as e: + logger.error( + "[GridTradingBot.record_transaction] Transaction recording failed: %s", + str(e), + ) + return False + def api_get_price(self) -> float: """获取当前市场价格""" logger.custom_debug( @@ -359,9 +437,8 @@ class GridTradingBot: order_id, self.active_orders[order_id].filled_time, ) + self.record_transaction(order_info) - # 如果订单已完成或已取消,从活跃订单中移除 - # if new_status in ["FILLED", "CANCELED"]: if new_status in ["CANCELED"]: logger.custom_debug( "[GridTradingBot.api_update_order_statuses] Removing order %s from active orders (status: %s)", @@ -832,6 +909,8 @@ class GridTradingBot: if __name__ == "__main__": config = { "symbol": "BTCUSDC", # 交易对 + "csv_symbol": "BTCUSDT", # CSV记录映射交易对 + "csv_file": "output/mexc_spot_grid_trades.csv", # CSV记录文件 "grid_percentage": 0.001, # 等比网格的公比 "grid_count": 3, # 单侧的挂单数,实时平衡 "order_amount": 0.00001, # BTC数量