feat(tool): CSV merge trades for the same pair on the same day
This commit is contained in:
		
							
								
								
									
										129
									
								
								tool_csv_merge.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								tool_csv_merge.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,129 @@
 | 
				
			|||||||
 | 
					"""CSV 文件处理模块
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					该模块用于合并同一证券在同一天的多笔交易记录,并生成汇总后的交易记录。
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import csv
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					from collections import defaultdict
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def process_csv(input_file, output_file):
 | 
				
			||||||
 | 
					    """处理CSV文件,合并相同证券在同一天的交易记录
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Args:
 | 
				
			||||||
 | 
					        input_file (str): 输入CSV文件路径
 | 
				
			||||||
 | 
					        output_file (str): 输出CSV文件路径
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    merged_records = defaultdict(
 | 
				
			||||||
 | 
					        lambda: {
 | 
				
			||||||
 | 
					            "buy_shares": 0.0,
 | 
				
			||||||
 | 
					            "buy_amount": 0.0,
 | 
				
			||||||
 | 
					            "sell_shares": 0.0,
 | 
				
			||||||
 | 
					            "sell_amount": 0.0,
 | 
				
			||||||
 | 
					            "order_ids": set(),
 | 
				
			||||||
 | 
					            "first_record": None,
 | 
				
			||||||
 | 
					            "time_part": None,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with open(input_file, mode="r", newline="", encoding="utf-8") as infile:
 | 
				
			||||||
 | 
					        reader = csv.DictReader(infile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for row in reader:
 | 
				
			||||||
 | 
					            datetime_str = row["日期"]
 | 
				
			||||||
 | 
					            date_part, time_part = datetime_str.split("T")
 | 
				
			||||||
 | 
					            order_id = row["备注"].split("Order ID: ")[-1].strip()
 | 
				
			||||||
 | 
					            merge_key = (date_part, row["证券代码"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            record = merged_records[merge_key]
 | 
				
			||||||
 | 
					            if record["first_record"] is None:
 | 
				
			||||||
 | 
					                record["first_record"] = row
 | 
				
			||||||
 | 
					                record["time_part"] = time_part
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            record["order_ids"].add(order_id)
 | 
				
			||||||
 | 
					            if row["类型"] == "买入":
 | 
				
			||||||
 | 
					                record["buy_shares"] += float(row["份额"])
 | 
				
			||||||
 | 
					                record["buy_amount"] += float(row["净额"])
 | 
				
			||||||
 | 
					            elif row["类型"] == "卖出":
 | 
				
			||||||
 | 
					                record["sell_shares"] += float(row["份额"])
 | 
				
			||||||
 | 
					                record["sell_amount"] += float(row["净额"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    output_rows = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for key, record in merged_records.items():
 | 
				
			||||||
 | 
					        date_part, symbol = key
 | 
				
			||||||
 | 
					        first_row = record["first_record"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        net_shares = record["buy_shares"] - record["sell_shares"]
 | 
				
			||||||
 | 
					        net_amount = record["buy_amount"] - record["sell_amount"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if net_shares >= 0:
 | 
				
			||||||
 | 
					            operation_type = "买入"
 | 
				
			||||||
 | 
					            display_shares = net_shares
 | 
				
			||||||
 | 
					            display_amount = net_amount
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            operation_type = "卖出"
 | 
				
			||||||
 | 
					            display_shares = -net_shares
 | 
				
			||||||
 | 
					            display_amount = -net_amount
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # 格式化为完整小数形式,不使用科学计数法
 | 
				
			||||||
 | 
					        formatted_shares = (
 | 
				
			||||||
 | 
					            f"{display_shares:f}".rstrip("0").rstrip(".")
 | 
				
			||||||
 | 
					            if "." in f"{display_shares:f}"
 | 
				
			||||||
 | 
					            else f"{display_shares:f}"
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        formatted_amount = (
 | 
				
			||||||
 | 
					            f"{display_amount:f}".rstrip("0").rstrip(".")
 | 
				
			||||||
 | 
					            if "." in f"{display_amount:f}"
 | 
				
			||||||
 | 
					            else f"{display_amount:f}"
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        merged_row = {
 | 
				
			||||||
 | 
					            "日期": f"{date_part}T{record['time_part']}",
 | 
				
			||||||
 | 
					            "类型": operation_type,
 | 
				
			||||||
 | 
					            "证券代码": symbol,
 | 
				
			||||||
 | 
					            "份额": formatted_shares,
 | 
				
			||||||
 | 
					            "净额": formatted_amount,
 | 
				
			||||||
 | 
					            "现金账户": first_row["现金账户"],
 | 
				
			||||||
 | 
					            "目标账户": first_row["目标账户"],
 | 
				
			||||||
 | 
					            "备注": f"MEXC API - Order ID: {', '.join(sorted(record['order_ids']))}",
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        output_rows.append(merged_row)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # 写入输出文件
 | 
				
			||||||
 | 
					    with open(output_file, mode="w", newline="", encoding="utf-8") as outfile:
 | 
				
			||||||
 | 
					        fieldnames = [
 | 
				
			||||||
 | 
					            "日期",
 | 
				
			||||||
 | 
					            "类型",
 | 
				
			||||||
 | 
					            "证券代码",
 | 
				
			||||||
 | 
					            "份额",
 | 
				
			||||||
 | 
					            "净额",
 | 
				
			||||||
 | 
					            "现金账户",
 | 
				
			||||||
 | 
					            "目标账户",
 | 
				
			||||||
 | 
					            "备注",
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					        writer = csv.DictWriter(outfile, fieldnames=fieldnames)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        writer.writeheader()
 | 
				
			||||||
 | 
					        writer.writerows(output_rows)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def process_all_csvs(input_dir="output"):
 | 
				
			||||||
 | 
					    """处理指定目录下的所有CSV文件
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Args:
 | 
				
			||||||
 | 
					        input_dir (str): 包含CSV文件的目录路径
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    for filename in os.listdir(input_dir):
 | 
				
			||||||
 | 
					        if filename.endswith(".csv") and not filename.startswith("merged_"):
 | 
				
			||||||
 | 
					            input_path = os.path.join(input_dir, filename)
 | 
				
			||||||
 | 
					            output_path = os.path.join(input_dir, f"merged_{filename}")
 | 
				
			||||||
 | 
					            process_csv(input_path, output_path)
 | 
				
			||||||
 | 
					            print(f"处理完成: {filename} -> merged_{filename}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == "__main__":
 | 
				
			||||||
 | 
					    process_all_csvs()
 | 
				
			||||||
 | 
					    print("所有文件处理完成")
 | 
				
			||||||
		Reference in New Issue
	
	Block a user