摘要
本文基于 Python+MiniQMT 实现 A 股经典尾盘策略的全自动化,完成14:55 同花顺问财选股→CSV 存盘→14:57 自动读取并批量下单的完整流程。提供修正后可直接运行的精简代码,同时给出核心优化方向,适合上班族及量化入门者快速上手。
一、前言
尾盘选股凭借低风险、短持股、高资金效率的特点,成为 A 股主流交易策略之一。但手动盯盘选股、下单效率低且易受情绪影响。本文通过 MiniQMT 实现全流程自动化,解放人力同时提升交易执行力。
二、核心原理与系统架构
2.1 尾盘策略逻辑
- 时间窗口:14:30-15:00,当日走势基本定型,波动风险低
- 核心优势:仅承受隔夜风险,主力尾盘调仓行为暴露次日方向
- 盈利逻辑:尾盘强势股次日大概率高开 / 冲高,实现 T+1 套利
2.2 系统架构
采用 "选股 + 交易" 解耦设计,通过 CSV 文件交互:
| 模块 | 执行时间 | 核心功能 |
|---|---|---|
| 选股模块 | 14:55 | 调用问财 API 筛选股票,生成当日选股 CSV |
| 交易模块 | 14:57 | MiniQMT 读取 CSV,自动计算仓位并下单 |
三、精简可运行代码
3.1 环境准备
- 登录 MiniQMT 并开启 Python API 权限
- 安装依赖:
pip install pywencai pandas schedule
3.2 完整代码
import pywencai
import pandas as pd
import logging
import os
import time
from datetime import datetime
from tquant import xt_trader, xtconstant
# 全局配置
LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s'
logging.basicConfig(level=logging.INFO, format=LOG_FORMAT, handlers=[
logging.FileHandler('tail_trade.log'), logging.StreamHandler()
])
logger = logging.getLogger(__name__)
# ---------------------- 选股模块 ----------------------
def get_stock_list():
"""自定义问财选股条件,返回股票DataFrame"""
try:
# 可修改为自己的选股条件
query = "流通市值<50亿,换手率3%-10%,涨幅2%-5%,量比>1.5,非ST,非创业板,非北交所"
df = pywencai.get(query=query, loop=True)
logger.info(f"选股完成,共{len(df) if df is not None else 0}只")
return df
except Exception as e:
logger.error(f"选股失败: {e}")
return None
def save_csv(data):
"""保存选股结果到带日期的CSV文件"""
if not data: return None
os.makedirs('data', exist_ok=True)
filename = f'data/tail_select_{datetime.now().strftime("%Y%m%d")}.csv'
data.to_csv(filename, index=False, encoding='utf-8-sig')
return filename
# ---------------------- 交易模块 ----------------------
class QMTTrade:
def __init__(self):
self.account = xt_trader.get_account_list()[0] if xt_trader.get_account_list() else None
def get_price(self, code):
"""获取卖一价作为买入价,确保成交"""
tick = xt_trader.get_full_tick([code])
return tick[code]['askPrice1'] if (tick and code in tick) else 0
def buy(self, code, quantity, price):
"""执行买入下单"""
return xt_trader.order(self.account, code, xtconstant.STOCK_BUY, price, quantity)
def run(self, csv_file):
"""执行交易主逻辑"""
if not self.account:
logger.error("无可用交易账户")
return
# 读取选股文件
df = pd.read_csv(csv_file, encoding='utf-8-sig')
if len(df) == 0: return
# 获取可用资金
balance = xt_trader.get_account_balance(self.account)
available = balance['cash'] - balance['frozen_cash']
logger.info(f"可用资金: {available:.2f}元")
# 自动识别股票代码列
code_col = next((c for c in ['code','股票代码','symbol'] if c in df.columns), None)
if not code_col:
logger.error("未找到股票代码列")
return
# 批量下单
success = 0
for i, row in df.iterrows():
if i >= 5: break # 最多买5只
code = str(row[code_col]).strip()
if '.' not in code: # 转换为QMT标准代码
code += '.SH' if code.startswith('6') else '.SZ'
price = self.get_price(code)
if price <= 0: continue
# 每只股票用5%资金,取整100股
qty = int(available * 0.05 / price / 100) * 100
if qty < 100: continue
if self.buy(code, qty, price):
logger.info(f"买入成功: {code} {qty}股 @ {price:.2f}")
success += 1
time.sleep(0.5)
logger.info(f"交易完成: 成功{success}只")
# ---------------------- 定时任务 ----------------------
def selection_task():
data = get_stock_list()
if data is not None:
save_csv(data)
def trade_task():
csv_file = f'data/tail_select_{datetime.now().strftime("%Y%m%d")}.csv'
if os.path.exists(csv_file):
QMTTrade().run(csv_file)
else:
logger.warning("今日无选股文件")
if __name__ == "__main__":
import schedule
schedule.every().day.at("14:55").do(selection_task)
schedule.every().day.at("14:57").do(trade_task)
logger.info("尾盘交易系统启动,等待执行...")
while True:
schedule.run_pending()
time.sleep(1)
四、使用说明
- 修改
get_stock_list函数中的query变量,替换为自己的选股条件 - 调整
run方法中的max_stocks(默认 5 只)和position_ratio(默认 5%) - 将代码复制到 MiniQMT Python 编辑器中运行,系统自动等待定时执行
- 查看
tail_trade.log获取运行日志和交易记录
五、常见问题
- 问财数据为空:简化选股条件,避免过于复杂的逻辑组合
- 下单失败 :确认股票代码格式为
xxx.SZ/SH,账户资金充足且股票未停牌 - 定时不执行:检查系统时间是否正确,程序是否保持后台运行
六、进阶扩展
- 增加次日 9:30 自动止盈止损卖出
- 加入企业微信 / 钉钉交易通知推送
- 引入技术指标二次过滤选股结果
- 添加单日最大亏损风控机制
七、免责声明
本文代码及策略仅供学习交流,不构成任何投资建议。量化交易存在风险,请谨慎决策并自行承担交易后果。