在量化交易的世界里,摆脱平台内置编辑器的束缚,实现本地化脚本开发是每个进阶交易者的必经之路。本文将带你用Python和XtQuant库,为安信证券QMT极简版打造一个完全自主控制的自动化交易系统。不同于平台内置的封闭环境,这种开发方式让你能使用熟悉的IDE工具、版本控制系统,以及更丰富的Python生态库。
首先确保你的系统安装了64位Python 3.6到3.11之间的版本(QMT极简版目前支持的版本范围)。推荐使用conda创建独立环境:
bash复制conda create -n qmt_trading python=3.8
conda activate qmt_trading
接下来安装交易脚本所需的辅助库:
bash复制pip install pandas numpy loguru schedule
注意:不要使用pip直接安装XtQuant,这个库需要从迅投官网手动下载
XtQuant文件夹解压到你的项目目录中code复制/your_project
├── XtQuant/
│ ├── __init__.py
│ ├── XtData.py
│ └── XtTrader.py
├── configs/
├── strategies/
└── main.py
创建qmt_connector.py文件,编写连接核心逻辑:
python复制from XtQuant import XtQuantTrader, XtQuantData
class QMTConnector:
def __init__(self, account_id, client_path):
self.account_id = account_id
self.client_path = client_path # QMT极简版安装路径
self.trader = XtQuantTrader(client_path, account_id)
self.data = XtQuantData(client_path)
def connect(self):
try:
self.trader.start()
self.data.start()
return True
except Exception as e:
print(f"连接失败: {str(e)}")
return False
连接过程中可能会遇到以下典型问题:
错误1:无法找到MiniQmt客户端
client_path是否指向正确的QMT极简版安装目录错误2:账号未授权当前设备
错误3:Python版本不兼容
XtQuant的行情模块提供多种数据订阅方式:
python复制def subscribe_market_data(self, stock_codes):
"""订阅实时行情"""
self.data.subscribe(stock_codes,
callback=self._on_market_data)
def _on_market_data(self, data):
"""行情回调处理"""
print(f"收到行情数据: {data}")
# 这里可以添加策略逻辑判断
获取K线历史数据示例:
python复制def get_history_data(self, stock_code, period, start_time, end_time):
"""
获取历史K线数据
:param period: '1m', '5m', '1d'等
"""
data = self.data.get_history_data(
stock_code,
period,
start_time,
end_time
)
return pd.DataFrame(data)
在trading_engine.py中实现核心交易方法:
python复制def place_order(self, stock_code, price, volume, order_type):
"""发送委托单"""
order = {
'stock_code': stock_code,
'price': price,
'volume': volume,
'order_type': order_type # 0-买, 1-卖
}
result = self.trader.place_order(order)
if result['success']:
print(f"委托成功: {result['order_id']}")
else:
print(f"委托失败: {result['error_msg']}")
实现订单状态查询和回调处理:
python复制def query_orders(self):
"""查询当日所有委托"""
return self.trader.query_orders()
def _on_order_status(self, order):
"""订单状态变更回调"""
print(f"订单状态更新: {order['status']}")
if order['status'] == '全部成交':
self._process_completed_order(order)
使用systemd创建后台服务(Linux系统):
bash复制# /etc/systemd/system/qmt_trading.service
[Unit]
Description=QMT Trading Service
After=network.target
[Service]
User=your_username
WorkingDirectory=/path/to/your/project
ExecStart=/path/to/python /path/to/your/project/main.py
Restart=always
[Install]
WantedBy=multi-user.target
配置完善的日志系统:
python复制from loguru import logger
logger.add("logs/trading_{time}.log",
rotation="100 MB",
retention="30 days",
level="DEBUG")
try:
strategy.run()
except Exception as e:
logger.error(f"策略运行异常: {e}")
# 紧急平仓逻辑
emergency_close_positions()
python复制class PortfolioManager:
def __init__(self, trader):
self.trader = trader
self.positions = self._load_positions()
def rebalance(self, target_allocation):
"""调整持仓至目标比例"""
current_value = self.get_portfolio_value()
for code, target in target_allocation.items():
target_value = current_value * target
self._adjust_position(code, target_value)
def _adjust_position(self, code, target_value):
"""调整单个标的持仓"""
current = self.positions.get(code, 0)
delta = target_value - current
if delta > 0:
self._buy(code, delta)
elif delta < 0:
self._sell(code, abs(delta))
实现基础风控检查:
python复制class RiskManager:
MAX_LOSS_PER_DAY = -0.05 # 单日最大亏损5%
def check_order(self, order):
"""下单前风控检查"""
if not self._check_position_limit(order):
return False
if not self._check_daily_loss():
return False
return True
def _check_daily_loss(self):
today_pnl = self.get_daily_pnl()
return today_pnl > self.MAX_LOSS_PER_DAY
python复制# 不好的做法:全市场订阅
data.subscribe(all_stocks)
# 推荐做法:按策略需要订阅
active_stocks = filter_active_stocks()
data.subscribe(active_stocks)
python复制from functools import lru_cache
@lru_cache(maxsize=1000)
def get_stock_name(stock_code):
"""缓存股票名称查询"""
return data.get_stock_name(stock_code)
在实际项目中,我发现将高频访问但不常变的数据(如股票基本信息)缓存在内存中可以显著降低对QMT接口的调用频率。一个典型的日内交易脚本经过优化后,接口调用次数可以从每分钟数百次下降到几十次,大幅提高了系统稳定性。