返回列表 发布新帖

2常见量化问题解答

18 0

今天继续按计划给大家更新量化教程,今天更新ptrade常见问题第二期,前面更新了一个内容ptrade常见问题-常见问题解答第一篇

更新的内容计划,前面更新了算法研究--日内拐点交易算法原理研究,点赞加关注后面持续更新内容

1 策略算法原理
2qmt使用教程
3策略算法原理
4量化研报
5 ptrad使用教程
6 因子分析
7策略算法原理

666448210fad1e30b0a21127673da972.png

1run_daily用法及运行时间

1、该函数用于以日为单位周期性运行指定函数,可对运行触发时间进行指定。

2、该函数只能在初始化阶段initialize函数中调用。

3、该函数可以在initialize中多次调用,以实现多个定时任务。但需要注意的是交易中定时任务线程数限制为5且累计的任务不执行,即run_daily和run_interval累计调用超过5次时,将会因堵塞导致部分定时任务不触发。

4、股票策略回测中,当回测周期为分钟时,time的取值指在09:31~11:30与13:00~15:00之间,当回测周期为日时,无论设定值是多少都只会在15:00执行;交易中不受此时间限制。

c8eead0180920a10fe3465c14e491cbe.png

代码框架参考

# -*- coding: utf-8 -*-
"""
run_daily 用法示例(优化版)
展示了多个定时任务的配置方式,避免与内部函数名冲突
"""
def initialize(context):
    # 设置股票池
    g.security = '6.SS'
    set_universe(g.security)


    # ==================== 多个定时任务示例 ====================


    # 1. 盘前任务:9:02 运行(交易环境可用)
    run_daily(context, my_before_market_open, time='09:02')


    # 2. 集合竞价任务:9:23 运行(回测分钟级可用)
    run_daily(context, my_aggregate_auction_func, time='9:23')


    # 3. 盘中任务:10:00 运行(回测分钟级可用)
    run_daily(context, my_mid_day_task, time='10:00')


    # 4. 尾盘任务:14:50 运行(回测分钟级可用)
    run_daily(context, my_after_market_close, time='14:50')


    # 5. 盘后任务:15:10 运行(交易环境可用,回测日线级在15:00执行)
    run_daily(context, my_post_market_task, time='15:10')


    log.info("定时任务设置完成,共5个任务")
# ==================== 定时任务函数定义 ====================
def my_before_market_open(context):
    """盘前任务:9:02 执行"""
    log.info(f"盘前任务执行 - {context.current_dt}")
    # 获取历史数据等准备工作
    history_data = get_history(10, '1d', 'close', g.security, fq='pre', include=True)
    log.info(f"获取历史数据完成")
def my_aggregate_auction_func(context):
    """集合竞价任务:9:23 执行"""
    log.info(f"集合竞价任务执行 - {context.current_dt}")
    stock = g.security
    # 获取最新价和涨停价
    snapshot = get_snapshot(stock)
    price = snapshot[stock]['last_px']
    up_limit = snapshot[stock]['up_px']
    # 如果最新价不小于涨停价则买入
    if float(price) >= float(up_limit):
        order(g.security, 100, limit_price=up_limit)
        log.info(f"集合竞价买入: {stock}")
def my_mid_day_task(context):
    """盘中任务:10:00 执行"""
    log.info(f"盘中任务执行 - {context.current_dt}")
    # 检查持仓状态
    positions = get_positions()
    log.info(f"当前持仓: {positions}")
def my_after_market_close(context):
    """尾盘任务:14:50 执行"""
    log.info(f"尾盘任务执行 - {context.current_dt}")
    # 执行调仓操作
    stock = g.security
    # 获取当前价格
    snapshot = get_snapshot(stock)
    price = snapshot[stock]['last_px']
    # 买入操作
    order(g.security, 100)
    log.info(f"尾盘买入: {stock}")
def my_post_market_task(context):
    """盘后任务:15:10 执行"""
    log.info(f"盘后任务执行 - {context.current_dt}")
    # 盘后处理:如逆回购、日志记录等
    cash = context.portfolio.cash
    log.info(f"盘后资金余额: {cash:.2f}")
# ==================== 必选函数 ====================
def handle_data(context, data):
    """盘中处理函数(日线级别每天15:00执行一次)"""
    # 日线策略中,handle_data 在15:00执行
    # 这里可以放置主要的交易逻辑
    pass

特别注意定时超了5个可能后面的模块拉不起来

# ❌ 错误写法:超过5个定时任务会导致部分任务不执行
run_daily(context, task1, time='09:00')
run_daily(context, task2, time='09:30')
run_daily(context, task3, time='10:00')
run_daily(context, task4, time='10:30')
run_daily(context, task5, time='11:00')
run_daily(context, task6, time='11:30')  # 第6个任务不会执行
# ✅ 正确写法:合并任务或减少任务数量
run_daily(context, combined_task, time='10:00')  # 将多个逻辑合并到一个函数

2run_interval用法及运行时间

1、该函数用于以设定时间间隔(单位为秒)周期性运行指定函数,可对运行触发时间间隔进行指定。

2、该函数只能在初始化阶段initialize函数中调用。

3、运行时间(1) PTrade1.0-QTV202501.04.000版本之前,启动当天根据启动时间+设置周期,第二天则是9:30 + 设置周期(2) PTrade1.0-QTV202501.04.000版本(含)之后,run_interval接口增加入参 interval_timer_ranges字段,支持设置运行的时间段,即支持配置24小时都能运行,例如配置:“09:15-11:30, 13:00-15:00”表示从上午9点15分到11点半和下午1点到3点的时间范围。

4、该函数可以在initialize中多次调用,以实现多个定时任务。但需要注意的是交易中定时任务线程数限制为5且累计的任务不执行,即run_daily和run_interval累计调用超过5次时,将会因堵塞导致部分定时任务不触发。

5、最小运行时间间隔seconds的设置规则:期货策略为1秒(用户设置值若小于1秒,系统仍当做1秒处理),股票等其他类型策略为3秒。

3a4f1106d1c3592e1d2dd254f1adf662.png

代码参考

# -*- coding: utf-8 -*-
"""
run_interval 用法示例(优化版)
展示了多个定时任务的配置方式,避免与内部函数名冲突
"""
def initialize(context):
    # 设置股票池
    g.security = '60.SS'
    set_universe(g.security)


    # ==================== 多个 run_interval 定时任务示例 ====================


    # 1. 每3秒运行一次(股票最小间隔)
    run_interval(context, my_tick_handle, seconds=3)


    # 2. 每10秒运行一次(常规间隔)
    run_interval(context, my_interval_handle, seconds=10)


    # 3. 每60秒运行一次(1分钟间隔)
    run_interval(context, my_minute_handle, seconds=60)


    log.info("定时任务设置完成,共3个任务")
# ==================== 定时任务函数定义 ====================
def my_tick_handle(context):
    """tick级别处理函数:每3秒执行一次"""
    log.info(f"tick级别任务执行 - {context.current_dt}")


    stock = g.security
    # 获取最新行情快照
    snapshot = get_snapshot(stock)
    price = snapshot[stock]['last_px']


    log.info(f"股票 {stock} 最新价: {price}")


    # 示例:简单的价格监控逻辑
    if price > 0:
        # 获取当前持仓
        position = get_position(stock)
        if position is None or position.amount == 0:
            # 没有持仓,考虑买入
            log.info(f"当前无持仓,监控价格: {price}")
        else:
            # 有持仓,监控盈亏
            cost = position.cost_basis
            profit_ratio = (price - cost) / cost * 100
            log.info(f"持仓盈亏比例: {profit_ratio:.2f}%")
def my_interval_handle(context):
    """常规间隔处理函数:每10秒执行一次"""
    log.info(f"常规间隔任务执行 - {context.current_dt}")


    # 获取账户信息
    total_value = context.portfolio.portfolio_value
    cash = context.portfolio.cash


    log.info(f"账户总资产: {total_value:.2f}, 可用资金: {cash:.2f}")


    # 获取当前持仓
    positions = get_positions()
    if positions:
        for stock, pos in positions.items():
            log.info(f"持仓 {stock}: {pos.amount}股, 成本 {pos.cost_basis:.2f}")
    else:
        log.info("当前无持仓")
def my_minute_handle(context):
    """分钟级别处理函数:每60秒执行一次"""
    log.info(f"分钟级别任务执行 - {context.current_dt}")


    stock = g.security
    # 获取历史数据用于技术分析
    history_data = get_history = get_history(5, '1d', 'close', stock, fq='pre', include=True)


    if history_history is not None and not history_history.empty:
        close_prices = history_history['close'].values
        ma5 = close_prices.mean()


        # 获取当前价格
        snapshot = get_snapshot(stock)
        current_price = snapshot[stock]['last_px']


        log.info(f"股票 {stock} 当前价: {current_price:.2f}, 5日均线: {ma5:.2f}")


        # 示例:均线策略逻辑
        if current_price > ma5:
            log.info(f"价格在均线上方,趋势偏多")
        else:
            log.info(f"价格在均线下方,趋势偏空")
# ==================== 必选函数 ====================
def handle_data(context, data):
    """盘中处理函数(日线级别每天15:00执行一次)"""
    # 日线策略中,handle_data 在15:00执行
    # 这里可以放置主要的交易逻辑
    pass

注意默认的数量5个

# ❌ 错误写法:超过5个定时任务会导致部分任务不执行
run_interval(context, my_task1, seconds=3)
run_interval(context, my_task2, seconds=5)
run_interval(context, my_task3, seconds=10)
run_interval(context, my_task4, seconds=30)
run_interval(context, my_task5, seconds=60)
run_interval(context, my_task6, seconds=120)  # 第6个任务不会执行
# ✅:合并任务或减少任务数量
run_interval(context, my_combined_task, seconds=10)  # 将多个逻辑合并到一个函数

最小间隔设置

# 股票策略:最小间隔为3秒
run_interval(context, my_task, seconds=3)  # ✅ 有效
run_interval(context, my_task, seconds=1)  # ❌ 会被自动调整为3秒
# 期货策略:最小间隔为1秒
run_interval(context, my_task, seconds=1)  # ✅ 有效
run_interval(context, my_task, seconds=0.5)  # ❌ 会被自动调整为1秒

多线程并行注意事项

def initialize(context):
    # 多个 run_interval 会以多个线程并行运行
    run_interval(context, my_task_a, seconds=3)
    run_interval(context, my_task_b, seconds=5)


    # ⚠️ 小心不同线程之间的逻辑关联处理
    # 例如:不要在多个线程中同时修改同一个全局变量而不加锁
def my_task_a(context):
    # 线程A:读取数据
    g.shared_data = get_snapshot(g.security)  # 可能被线程B同时修改
def my_task_b(context):
    # 线程B:写入数据
    g.shared_data = get_history(10, '1d', 'close', g.security)  # 可能覆盖线程A的数据

3量化策略报错:无法获取到000300.SH对应的数据,设置基准失败。

1、量化中上海市场代码的尾缀为SS,不是SH,客户可将000300.SH改成000300.SS;

2、代码不确定尾缀的可以在量化回测策略中,输入代码即可联想到后缀,选择即可。

6ad9b181b70323ab04387b708bbf66db.png

4量化的历史行情数据,支持什么周期的?

frequency:K线周期,现有支持1分钟线(1m)、5分钟线(5m)、15分钟线(15m)、30分钟线(30m)、60分钟线(60m)、120分钟线(120m)、日线(1d)、周线(1w/weekly)、月线(mo/monthly)、季度线(1q/quarter)和年线(1y/yearly)频率的数据。

0a31ce2b1b1a6971234d67ac645067dd.png

5量化get_price/get_history接口能获取多久之前的数据。

能获取2005年后的数据,具体以客户环境的历史数据为准,一般生产环境能获取2005年之后的数据

7612508c69913567898caa6b6cc424e2.png

6get_history函数include参数说明

get_history当日数据时include参数如果是true,就取行情服务器最新一根k线;如果是false,就是取最新一根k线的上一根。

e97a01db5533ba79d5bd931ca1e8322c.png

7一分钟线与多分钟周期数据get_history 取值逻辑

1、逻辑都是:比如9:47:40秒获取,include = True, 分钟线是获取到094700的数据,五分钟线实际获取到的是9.47时候的五分钟线,此时的时间戳是9.50; 2、分钟线将最新的一根切除了,五分钟线没有切除,也就是五分钟线是实时请求到行情服务器最新的结果; 3、其他多分钟周期的,跟五分钟逻辑一样

664da17106d323faa4d421165fb8397d.png

8get_history函数取五分钟线,include使用true和false有什么区别?

1、使用true时,会包含最新生成的五分钟线,例如10.35.33执行,会获取到10.40.00这一根五分钟线(行情实时生成变化,在某一分钟内是一个定值);

2、若是false时,则在10.35.33执行的语句只能获取到10.35.00着一根五分钟线,为已经结束的时间内的五分钟线,不再会变化。

cd54c79da027fe409c522b94e73c86fe.png

9 9点30分46秒调用 get_history(include=True)没有取到当日最新的数据。

此为正常现象,需要到9点31之后才可取到当日最新的数据,对于分钟k线,include=True取到的是最新的 一根完整K线,对于日线来说,9点31分前的取到的是一上一交易日的日线,9点31分后取到的是当前交易日最新的日线。

33d5b9bbbaeabb3a8566458da8c56906.png

10 量化中获取很多代码的收盘价有误差?

东财软件/同花顺/通达信默认开启复权,量化get_price、get_history接口fq-数据复权选项不设置默认不开启,所以客户对比会有误差。客户可将两个软件都调整为复权或者不复权再进行对比,正常。

7836af4086f9111939bfc7d819b35f80.png

更多的内容后面的教程继续更新

0492805cf7749b104320f6b4fd4d988b.png

不懂的内容问我就可以,加我备注入群可以加入量化交流群,我专业技术支持

db3dc3563ef65ca7e437cf19c3d1c018.jpg

量化开户服务需要的找我就可以

9a3ed99c09d4215e61cd5dbd080710ea.png

回复

您需要登录后才可以回帖 登录 | 立即注册

客服专线

400-080-8112

用思考的速度交易,用真诚的态度合作,我们是认真的!
  • 关注公众号
  • 添加微信客服
Copyright © 2001-2026 迅投QMT社区 版权所有 All Rights Reserved. 京ICP备2025122616号-3
关灯 快速发帖
扫一扫添加微信客服
QQ客服返回顶部
快速回复 返回顶部 返回列表