在金融市场的复杂世界中,投资者和交易者不断寻找能够提供优势的策略。学术论文,尤其是那些深入探讨市场行为和策略表现的研究,可以成为这些策略灵感的丰富源泉。本文将聚焦于一种特定的交易策略——隔夜反转策略(overnight-intraday reversal strategy,简称CO-OC),这是一种基于证券隔夜回报率来预测其日内表现的策略。我们将探讨这种策略的原理、合理性、适用场景以及基本逻辑,以展示如何从学术研究中提炼出实际可行的交易策略。
隔夜反转策略的核心在于捕捉隔夜(闭市到开市)回报率与随后日内(开市到闭市)回报率之间的反向关系。研究表明,购买隔夜回报率低的证券并卖出隔夜回报率高的证券,能够在多个主要资产类别中实现显著的日内回报和夏普比率,这些回报是传统日内反转策略的两到五倍。
隔夜反转策略的合理性基于以下几点:
隔夜反转策略在全球多个资产类别中都显示出潜在的应用价值,包括但不限于股指期货、利率期货、商品期货和货币期货。该策略特别适用于寻求利用日内价格波动的交易者,以及在市场流动性发生变化时,如市场波动性增加或减少的情况下。
通过深入分析学术论文,我们不仅能够理解隔夜反转策略的理论基础,还能够洞察其在实际交易中的应用。下文将详细探讨如何将这些学术理论转化为实际的交易策略。
中国商品期货市场具有独特的交易特性和流动性,这为策略的实施提供了理想的测试环境。我们将在优宽量化平台进行策略的实现,这是一个为量化交易者提供强大工具和数据支持的平台。
// 定义两个数组,包含具有夜盘交易的商品期货合约代码
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秒
}
}
初始化:定义两个数组nightContract2
和nightContract
,分别包含所有具有夜盘的合约和挑选出的流动性较高的合约,大家可以根据对不同品种的了解程度进行更多合约的筛选。products
数组用于存储主力合约代码。
主函数main
:在无限循环中,根据当前时间执行不同的操作。
08:55操作:如果时间为开盘前5分钟08:55,获取目标合约列表并根据前一日的开盘至收盘价涨幅进行排名,选择涨幅最大的5个合约作为空头目标,跌幅最大的5个合约作为多头目标。
09:00操作:如果时间为开盘整点时间09:00,根据上一步得到的目标合约列表开仓。
持仓信息:交易时间段内,实时获取并打印当前持仓信息。
14:58操作:如果时间为交易末尾时分14:58,平掉所有持仓,准备下一日的交易。
休眠:每10秒执行一次循环,以减少资源消耗并避免过度交易。
自2024年6月份起对策略进行回测,结果还算不错,赚了12415元。这个策略挺聪明的,知道什么时候该做多,什么时候该做空,具有一定的风险对冲能力。虽然现在这个版本还比较简单,但基本的框架还是可以使用的。有兴趣的朋友可以在此基础上增加更多功能模块,比如更精细的风险控制,让策略可以更加平稳运行。
怎么样?从一篇学术论文的灵感出发,到策略在优宽量化平台上的实现,这一路走来还挺有趣的。这不仅仅是一次学术到实践的跳跃,更像是一次头脑风暴的冒险。我们把那些复杂的理论简化成了几行代码,让它们在市场中跑了起来。现在这个策略还只是个雏形,期待大家在此基础上继续发挥创意,调调参数,或许下一个量化交易大师就是你!
参考文献:
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
注: 本文仅做探索性尝试,不构成任何投资性建议。