资源加载中... loading...

如何从学术论文中获取策略灵感:隔夜反转策略实现

Author: ianzeng123, Created: 2024-11-14 16:25:50, Updated: 2024-11-19 13:22:04

img

引言

在金融市场的复杂世界中,投资者和交易者不断寻找能够提供优势的策略。学术论文,尤其是那些深入探讨市场行为和策略表现的研究,可以成为这些策略灵感的丰富源泉。本文将聚焦于一种特定的交易策略——隔夜反转策略(overnight-intraday reversal strategy,简称CO-OC),这是一种基于证券隔夜回报率来预测其日内表现的策略。我们将探讨这种策略的原理、合理性、适用场景以及基本逻辑,以展示如何从学术研究中提炼出实际可行的交易策略。

img

策略原理

隔夜反转策略的核心在于捕捉隔夜(闭市到开市)回报率与随后日内(开市到闭市)回报率之间的反向关系。研究表明,购买隔夜回报率低的证券并卖出隔夜回报率高的证券,能够在多个主要资产类别中实现显著的日内回报和夏普比率,这些回报是传统日内反转策略的两到五倍。

合理性

隔夜反转策略的合理性基于以下几点:

  • 统计证据:研究提供了强有力的统计证据,支持该策略在多个资产类别中的有效性。
  • 经济机制:策略的成功归因于不同资产类别特定的市场流动性提供机制,尤其是市场制造者在面对隔夜回报率分散时的行为。
  • 风险调整后的表现:即使在考虑了多种风险因素后,该策略仍然显示出显著的超额回报,表明其回报不仅仅是风险的补偿。

适用场景

隔夜反转策略在全球多个资产类别中都显示出潜在的应用价值,包括但不限于股指期货、利率期货、商品期货和货币期货。该策略特别适用于寻求利用日内价格波动的交易者,以及在市场流动性发生变化时,如市场波动性增加或减少的情况下。

基本策略逻辑

  1. 信号生成:使用隔夜(闭市到开市)的回报率作为交易信号。
  2. 资产选择:购买隔夜回报率低的资产,卖出隔夜回报率高的资产。
  3. 持仓期间:在随后的日内(开市到闭市)期间持有这些头寸。
  4. 回报实现:在日内交易结束时实现利润或亏损。
  5. 风险控制:通过考虑市场流动性和资产类别特定的因素来调整策略,以控制潜在的风险。

通过深入分析学术论文,我们不仅能够理解隔夜反转策略的理论基础,还能够洞察其在实际交易中的应用。下文将详细探讨如何将这些学术理论转化为实际的交易策略。

策略实现

中国商品期货市场具有独特的交易特性和流动性,这为策略的实施提供了理想的测试环境。我们将在优宽量化平台进行策略的实现,这是一个为量化交易者提供强大工具和数据支持的平台。

// 定义两个数组,包含具有夜盘交易的商品期货合约代码
const nightContract2 = ['sc', 'ag', 'au', 'nr', 'bu', 'hc', 'rb', 'ru', 'sp', 'fu', 'CF', 'CY', 'FG', 'MA', 'PF', 'OI', 'RM', 'SR',
    'TA', 'SA', 'a', 'b', 'c', 'cs', 'i', 'j', 'jm', 'l', 'm', 'p', 'pp', 'v', 'y', 'eg', 'rr', 'eb', 'pg', 'lu',
    'PX', 'br', 'PR', 'SH', 'al', 'cu', 'ni', 'pb', 'sn', 'zn', 'ss', 'bc', 'ao'];

const nightContract = ['hc', 'rb', 'ru', 'sp', 'FG', 'MA', 'PF',  'SR',
    'TA', 'SA', 'c', 'i','jm', 'l', 'm', 'p', 'pp', 'v', 'y', 'eg', 'eb']; // 挑选流动性较高的具有夜盘的品种

// 主函数
function main() {
    // 为每个合约设置主力合约后缀“888”
    const products = nightContract.map(item => item + '888'); 
    let longList = []; // 多头持仓列表
    let shortList = []; // 空头持仓列表
    let checklock = true; // 检查锁,用于控制策略运行的开始
    let openlock = false; // 开仓锁,用于控制开仓操作的执行
    const p = $.NewPositionManager(); // 创建一个新的持仓管理器实例

    // 无限循环,持续运行策略
    while (true) {
        // 检查交易所是否连接正常
        if (!exchange.IO('status')) {
            Sleep(1000 * 10); // 如果连接不正常,等待10秒后继续检查
            continue;
        }

        // 获取当前时间
        const now = new Date();
        const timeString = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}`;
        const today = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;

        // 如果时间是08:55且checklock为真,则获取目标合约列表并进行排名
        if (timeString === '08:55' && checklock) { 
            // 清空长短期列表
            longList = [];
            shortList = [];

            // 遍历所有主力合约
            products.forEach(product => {
                const records = exchange.GetRecords(product, PERIOD_D1); // 获取日K线数据
                const nightr = records[records.length - 1]; // 获取最新的日K线数据
                const rtime = _D(nightr.Time).substring(0, 10); // 获取日期

                // 检查日期是否为今天
                if (rtime !== today) return;

                // 计算开盘至收盘价之间的涨幅
                const power = (nightr.Close - nightr.Open) / nightr.Open;
                // 如果涨幅大于1.5%,则加入空头列表;如果跌幅大于1.5%,则加入多头列表
                if (power > 1.5 / 100) {
                    shortList.push({ cursymbol: product, power });
                } else if (power < -1.5 / 100) {
                    longList.push({ cursymbol: product, power });
                }
            });

            // 对多头列表按涨幅从小到大排序,并取前5个
            longList = longList.sort((a, b) => a.power - b.power).slice(0, 5);
            // 对空头列表按跌幅从大到小排序,并取前5个
            shortList = shortList.sort((a, b) => b.power - a.power).slice(0, 5);

            // 将列表中的合约对象映射为合约代码
            longList = longList.map(item => item.cursymbol);
            shortList = shortList.map(item => item.cursymbol);

            // 打印获取的每日开仓数据
            Log('获取每日开仓数据', '#ff0000');
            Log('日多:', longList);
            Log('日空:', shortList);

            checklock = false; // 释放checklock锁
            openlock = true; // 设置openlock锁
        }

        // 如果时间是09:00且openlock为真,则开仓
        if (timeString === '09:00' && openlock) {
            // 对于多头列表中的合约,开多仓
            longList.forEach(product => {
                p.OpenLong(product, 1); // 开1手多单
            });

            // 对于空头列表中的合约,开空仓
            shortList.forEach(product => {
                p.OpenShort(product, 1); // 开1手空单
            });

            openlock = false; // 释放openlock锁
        }

        // 获取当前持仓信息
        var checkpos = exchange.GetPositions();
        if (typeof(checkpos) === 'undefined') return;

        // 构建持仓信息表格
        var talStatus = {
            type: "table",
            title: "持仓信息",
            cols: ["品种名称", "持仓方向", "持仓均价", "持仓数量", "持仓盈亏"],
            rows: []
        };

        // 如果有持仓,则添加到表格中
        if(checkpos.length > 0){
            for(var i of checkpos){
                var color = i.Profit > 0 ? '#ff0000' : '#00ff00'; // 盈利为红色,亏损为绿色
                talStatus.rows.push([i.Symbol, i.Type%2 == 0 ? '多头' : '空头', i.Price , i.Amount, i.Profit + color]);
            }
            LogStatus(talStatus); // 打印持仓信息
        } else {
            LogStatus("当前无持仓信息",'#FF0000'); // 如果没有持仓,则打印无持仓信息
        }

        // 如果时间是14:58且openlock为假,则平仓
        if (timeString === '14:58' && !openlock) {
            // 平掉所有持仓
            p.CoverAll();
            checklock = true; // 设置checklock锁
        }

        Sleep(1000 * 10); // 休眠10秒
    }
}

基本逻辑说明:

  1. 初始化:定义两个数组nightContract2nightContract,分别包含所有具有夜盘的合约和挑选出的流动性较高的合约,大家可以根据对不同品种的了解程度进行更多合约的筛选。products数组用于存储主力合约代码。

  2. 主函数main:在无限循环中,根据当前时间执行不同的操作。

  3. 08:55操作:如果时间为开盘前5分钟08:55,获取目标合约列表并根据前一日的开盘至收盘价涨幅进行排名,选择涨幅最大的5个合约作为空头目标,跌幅最大的5个合约作为多头目标。

  4. 09:00操作:如果时间为开盘整点时间09:00,根据上一步得到的目标合约列表开仓。

  5. 持仓信息:交易时间段内,实时获取并打印当前持仓信息。

  6. 14:58操作:如果时间为交易末尾时分14:58,平掉所有持仓,准备下一日的交易。

  7. 休眠:每10秒执行一次循环,以减少资源消耗并避免过度交易。

策略运行结果:

自2024年6月份起对策略进行回测,结果还算不错,赚了12415元。这个策略挺聪明的,知道什么时候该做多,什么时候该做空,具有一定的风险对冲能力。虽然现在这个版本还比较简单,但基本的框架还是可以使用的。有兴趣的朋友可以在此基础上增加更多功能模块,比如更精细的风险控制,让策略可以更加平稳运行。

img

感想:

怎么样?从一篇学术论文的灵感出发,到策略在优宽量化平台上的实现,这一路走来还挺有趣的。这不仅仅是一次学术到实践的跳跃,更像是一次头脑风暴的冒险。我们把那些复杂的理论简化成了几行代码,让它们在市场中跑了起来。现在这个策略还只是个雏形,期待大家在此基础上继续发挥创意,调调参数,或许下一个量化交易大师就是你!

参考文献:

Liu, Chun and Liu, Chun and Liu, Yang and Wang, Tianyu and Zhou, Guofu and Zhu, Yingzi, Overnight-Intraday Reversal Everywhere (December 31, 2016). Asian Finance Association (AsianFA) 2016 Conference, Available at SSRN: https://ssrn.com/abstract=2730304 or http://dx.doi.org/10.2139/ssrn.2730304

注: 本文仅做探索性尝试,不构成任何投资性建议。


更多内容