Initial commit: modular trading service architecture
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
交易服务核心类
|
||||
"""
|
||||
|
||||
from collections import deque, defaultdict
|
||||
from typing import List, Dict, Optional
|
||||
import threading
|
||||
|
||||
from models import TradeInstruction
|
||||
|
||||
|
||||
class TradingServer:
|
||||
"""交易服务主类"""
|
||||
|
||||
def __init__(self):
|
||||
# 交易指令队列 - 按SYMBOL分类
|
||||
# 结构: {"SYMBOL1": [TradeInstruction1, ...], "SYMBOL2": [...]}
|
||||
self.trade_instructions = defaultdict(list)
|
||||
|
||||
# 统计数据历史 - 保留最新10条
|
||||
# 结构: deque([{stat_data1}, {stat_data2}, ...], maxlen=10)
|
||||
self.statistics_history = deque(maxlen=10)
|
||||
|
||||
# 线程锁 - 确保线程安全
|
||||
self.lock = threading.RLock()
|
||||
|
||||
print("[信息] 交易服务已初始化")
|
||||
|
||||
def add_trade_instruction(self, instructions: List[TradeInstruction]) -> int:
|
||||
"""
|
||||
添加交易指令
|
||||
返回添加的指令数量
|
||||
在此处对缺失的 sl/tp 值进行补全:
|
||||
- sl 若未设置保持0.0
|
||||
- tp 若未设置则默认 0.005
|
||||
"""
|
||||
with self.lock:
|
||||
count = 0
|
||||
for instruction in instructions:
|
||||
# 填充默认值
|
||||
if instruction.sl is None:
|
||||
instruction.sl = 0.0
|
||||
if instruction.tp is None or instruction.tp <= 0.0:
|
||||
instruction.tp = 0.005
|
||||
|
||||
symbol = instruction.symbol.upper()
|
||||
self.trade_instructions[symbol].append(instruction)
|
||||
count += 1
|
||||
|
||||
print(f"[信息] 已添加 {count} 条交易指令")
|
||||
for symbol, trades in self.trade_instructions.items():
|
||||
print(f" {symbol}: {len(trades)} 条待执行")
|
||||
|
||||
return count
|
||||
|
||||
def get_trades_by_symbol(self, symbol: str, price: Optional[float] = None) -> List[Dict]:
|
||||
"""
|
||||
获取指定SYMBOL的交易指令并删除
|
||||
根据价格条件过滤指令:
|
||||
- 买入指令(action='b'):如果指令价格 > 当前价格,缓存(等待价格下跌到指令价格)
|
||||
- 卖出指令(action='s'):如果指令价格 < 当前价格,缓存(等待价格上涨到指令价格)
|
||||
返回指令列表(JSON格式)
|
||||
"""
|
||||
with self.lock:
|
||||
symbol = symbol.upper()
|
||||
if symbol not in self.trade_instructions or len(self.trade_instructions[symbol]) == 0:
|
||||
return []
|
||||
|
||||
# 获取所有指令
|
||||
trades = self.trade_instructions[symbol]
|
||||
result = []
|
||||
cached_trades = []
|
||||
|
||||
for t in trades:
|
||||
should_send = True
|
||||
|
||||
# 如果提供了价格,进行条件检查
|
||||
if price is not None:
|
||||
if t.action.lower() == 'b':
|
||||
# 买入指令:如果指令价格 > 当前价格,则缓存
|
||||
if t.price > price:
|
||||
should_send = False
|
||||
cached_trades.append(t)
|
||||
elif t.action.lower() == 's':
|
||||
# 卖出指令:如果指令价格 < 当前价格,则缓存
|
||||
if t.price < price:
|
||||
should_send = False
|
||||
cached_trades.append(t)
|
||||
|
||||
if should_send:
|
||||
result.append({
|
||||
"symbol": t.symbol.lower(),
|
||||
"action": t.action.lower(),
|
||||
"mount": t.mount,
|
||||
"price": t.price,
|
||||
"sl": t.sl,
|
||||
"tp": t.tp
|
||||
})
|
||||
|
||||
# 更新指令队列:移除已发送的,保留已缓存的
|
||||
self.trade_instructions[symbol] = cached_trades
|
||||
|
||||
if len(result) > 0:
|
||||
print(f"[信息] 推送了 {len(result)} 条 {symbol} 指令给EA (当前价格: {price})")
|
||||
if len(cached_trades) > 0:
|
||||
print(f"[信息] 缓存了 {len(cached_trades)} 条 {symbol} 指令,等待价格条件满足")
|
||||
|
||||
return result
|
||||
|
||||
def save_statistics(self, stat_data: dict) -> None:
|
||||
"""
|
||||
保存统计数据
|
||||
自动保留最新10条
|
||||
"""
|
||||
with self.lock:
|
||||
self.statistics_history.append(stat_data)
|
||||
print(f"[信息] 统计数据已记录 - {stat_data.get('timestamp', 'unknown')}")
|
||||
print(f" 当前保存数据条数: {len(self.statistics_history)}")
|
||||
|
||||
def get_latest_statistics(self, count: int = 10) -> List[Dict]:
|
||||
"""
|
||||
获取最新的统计数据
|
||||
"""
|
||||
with self.lock:
|
||||
return list(self.statistics_history)[-count:]
|
||||
|
||||
def get_all_pending_trades(self) -> Dict[str, List[Dict]]:
|
||||
"""
|
||||
获取所有待执行的交易指令(不删除)
|
||||
用于查询接口
|
||||
"""
|
||||
with self.lock:
|
||||
result = {}
|
||||
for symbol, trades in self.trade_instructions.items():
|
||||
result[symbol] = [
|
||||
{
|
||||
"symbol": t.symbol.lower(),
|
||||
"action": t.action.lower(),
|
||||
"mount": t.mount,
|
||||
"price": t.price,
|
||||
"sl": t.sl,
|
||||
"tp": t.tp
|
||||
}
|
||||
for t in trades
|
||||
]
|
||||
return result
|
||||
|
||||
def clear_trades(self, symbol: Optional[str] = None) -> int:
|
||||
"""
|
||||
清空交易指令
|
||||
如果指定symbol则只清空该symbol
|
||||
返回清空的指令数量
|
||||
"""
|
||||
with self.lock:
|
||||
if symbol is None:
|
||||
total = sum(len(trades) for trades in self.trade_instructions.values())
|
||||
self.trade_instructions.clear()
|
||||
print(f"[信息] 已清空所有交易指令,共 {total} 条")
|
||||
return total
|
||||
else:
|
||||
symbol = symbol.upper()
|
||||
count = len(self.trade_instructions.get(symbol, []))
|
||||
if symbol in self.trade_instructions:
|
||||
del self.trade_instructions[symbol]
|
||||
print(f"[信息] 已清空 {symbol} 的交易指令,共 {count} 条")
|
||||
return count
|
||||
Reference in New Issue
Block a user