添加仅模拟交易

This commit is contained in:
zhiyong 2025-04-30 10:06:18 +08:00
parent 02f67a2424
commit 893d679632
2 changed files with 102 additions and 41 deletions

View File

@ -2,12 +2,13 @@ import os
class Config:
# Server settings
PORT = int(os.getenv('TRADE_SERVER_PORT', 9527))
HOST = os.getenv('TRADE_SERVER_HOST', '0.0.0.0')
PORT = 9527
HOST = '0.0.0.0'
DEBUG = False
# Trading settings
TRADE_TIMEOUT = int(os.getenv('TRADE_TIMEOUT', 3)) # 交易超时时间(秒)
TRADE_TIMEOUT = 3 # 交易超时时间(秒)
SIMULATION_ONLY = True # 是否仅使用模拟交易
# Trading hours
MARKET_OPEN_TIME = "09:20"
@ -26,5 +27,5 @@ class Config:
RATE_LIMIT_PERIOD = 60 # seconds
# XtQuant 相关配置
XT_ACCOUNT = os.getenv('XT_ACCOUNT', '80391818')
XT_PATH = os.getenv('XT_PATH', r'C:\\江海证券QMT实盘_交易\\userdata_mini')
XT_ACCOUNT = '80391818'
XT_PATH = r'C:\\江海证券QMT实盘_交易\\userdata_mini'

View File

@ -101,9 +101,61 @@ def run_pending_tasks():
# Run the task scheduler in a new thread
threading.Thread(target=run_pending_tasks).start()
trader = XtTrader()
trader.login()
# 创建模拟交易类
class SimulationTrader:
def __init__(self):
self.logger = sim_logger
def login(self):
self.logger.info("模拟交易:登录成功")
return True
def logout(self):
self.logger.info("模拟交易:登出成功")
return True
def buy(self, code, price, amount):
message = f"模拟买入 - 代码: {code}, 价格: {price}, 数量: {amount}"
self.logger.info(message)
return {"order_id": "simulation", "message": message}
def sell(self, code, price, amount):
message = f"模拟卖出 - 代码: {code}, 价格: {price}, 数量: {amount}"
self.logger.info(message)
return {"order_id": "simulation", "message": message}
def cancel(self, entrust_no):
message = f"模拟撤单 - 委托号: {entrust_no}"
self.logger.info(message)
return {"order_id": "simulation", "message": message}
def get_balance(self):
message = "模拟交易:查询余额"
self.logger.info(message)
return {"cash": 1000000.00, "frozen": 0.00, "total": 1000000.00}
def get_positions(self):
message = "模拟交易:查询持仓"
self.logger.info(message)
return []
def get_today_trades(self):
message = "模拟交易:查询今日成交"
self.logger.info(message)
return []
def get_today_entrust(self):
message = "模拟交易:查询今日委托"
self.logger.info(message)
return []
def is_trading_time(self):
return True
# 根据配置选择交易实例
trader = SimulationTrader() if Config.SIMULATION_ONLY else XtTrader()
trader.login()
# 添加请求频率限制
app = Flask(__name__)
@ -139,37 +191,41 @@ def buy():
if price <= 0 or amount <= 0:
raise ValueError("Price and amount must be positive")
# 检查交易状态
# 检查是否需要模拟交易
should_simulate = True
simulation_reason = "未知原因"
if trader is None:
simulation_reason = "交易实例未初始化"
else:
if not Config.SIMULATION_ONLY:
try:
if not trader.is_trading_time():
simulation_reason = "当前为非交易时段"
else:
if trader.is_trading_time():
should_simulate = False
else:
simulation_reason = "当前为非交易时段"
except Exception as e:
simulation_reason = f"检查交易时间发生错误: {str(e)}"
if should_simulate:
# 记录模拟交易信息
# 使用模拟交易
sim_message = f"模拟买入 - {simulation_reason} - 代码: {code}, 价格: {price}, 数量: {amount}"
sim_logger.info(sim_message)
return jsonify({"success": True, "data": {"order_id": "simulation", "message": sim_message}}), 200
# 实际交易
# 尝试实盘交易
logger.info(f"Executing buy order: code={code}, price={price}, amount={amount}")
result = execute_with_timeout(trader.buy, Config.TRADE_TIMEOUT, code, price, amount)
if result is None:
logger.error(f"Buy order timeout after {Config.TRADE_TIMEOUT} seconds")
return jsonify({"success": False, "error": "Operation timeout"}), 408
logger.info(f"Buy order result: {result}")
response = {"success": True, "data": result}
return jsonify(response), 200
try:
result = execute_with_timeout(trader.buy, Config.TRADE_TIMEOUT, code, price, amount)
if result is None:
# 超时时使用模拟交易
sim_message = f"模拟买入 - 交易超时 - 代码: {code}, 价格: {price}, 数量: {amount}"
sim_logger.info(sim_message)
return jsonify({"success": True, "data": {"order_id": "simulation", "message": sim_message}}), 200
logger.info(f"Buy order result: {result}")
return jsonify({"success": True, "data": result}), 200
except Exception as e:
# 发生错误时使用模拟交易
sim_message = f"模拟买入 - 交易失败({str(e)}) - 代码: {code}, 价格: {price}, 数量: {amount}"
sim_logger.info(sim_message)
return jsonify({"success": True, "data": {"order_id": "simulation", "message": sim_message}}), 200
except ValueError as e:
logger.error(f"Invalid request parameters: {str(e)}")
abort(400, description=str(e))
@ -198,37 +254,41 @@ def sell():
if price <= 0 or amount <= 0:
raise ValueError("Price and amount must be positive")
# 检查交易状态
# 检查是否需要模拟交易
should_simulate = True
simulation_reason = "未知原因"
if trader is None:
simulation_reason = "交易实例未初始化"
else:
if not Config.SIMULATION_ONLY:
try:
if not trader.is_trading_time():
simulation_reason = "当前为非交易时段"
else:
if trader.is_trading_time():
should_simulate = False
else:
simulation_reason = "当前为非交易时段"
except Exception as e:
simulation_reason = f"检查交易时间发生错误: {str(e)}"
if should_simulate:
# 记录模拟交易信息
# 使用模拟交易
sim_message = f"模拟卖出 - {simulation_reason} - 代码: {code}, 价格: {price}, 数量: {amount}"
sim_logger.info(sim_message)
return jsonify({"success": True, "data": {"order_id": "simulation", "message": sim_message}}), 200
# 实际交易
# 尝试实盘交易
logger.info(f"Executing sell order: code={code}, price={price}, amount={amount}")
result = execute_with_timeout(trader.sell, Config.TRADE_TIMEOUT, code, price, amount)
if result is None:
logger.error(f"Sell order timeout after {Config.TRADE_TIMEOUT} seconds")
return jsonify({"success": False, "error": "Operation timeout"}), 408
logger.info(f"Sell order result: {result}")
response = {"success": True, "data": result}
return jsonify(response), 200
try:
result = execute_with_timeout(trader.sell, Config.TRADE_TIMEOUT, code, price, amount)
if result is None:
# 超时时使用模拟交易
sim_message = f"模拟卖出 - 交易超时 - 代码: {code}, 价格: {price}, 数量: {amount}"
sim_logger.info(sim_message)
return jsonify({"success": True, "data": {"order_id": "simulation", "message": sim_message}}), 200
logger.info(f"Sell order result: {result}")
return jsonify({"success": True, "data": result}), 200
except Exception as e:
# 发生错误时使用模拟交易
sim_message = f"模拟卖出 - 交易失败({str(e)}) - 代码: {code}, 价格: {price}, 数量: {amount}"
sim_logger.info(sim_message)
return jsonify({"success": True, "data": {"order_id": "simulation", "message": sim_message}}), 200
except ValueError as e:
logger.error(f"Invalid request parameters: {str(e)}")
abort(400, description=str(e))