一种基于价格比率和斜率变化的交易策略,旨在通过分析两个品种之间的价格比率及其变化趋势,进行多空双向交易。策略的核心在于利用斜率计算和价格回溯长度来判断市场趋势,并结合保证金比例和设定资金量来计算开仓手数和出场条件。
- 策略概述:基于价格比率和斜率变化的交易策略,适用于两个品种的多空双向交易。
- 关键参数:包括双边保证金、保证金比例、斜率计算长度、价格比回溯长度和吊顶出场回撤系数。
- 交易逻辑:通过计算价格比率及其斜率,判断市场趋势,进行多空开仓和出场操作。
- 风险管理:利用设定的保证金比例和资金量计算开仓手数,并通过吊顶出场方式控制风险。
策略原理
该策略的核心在于通过分析两个品种之间的价格比率及其变化趋势来进行交易决策。具体来说,策略的主要步骤包括:
1. 数据准备:在初始化阶段,设置数据后复权、映射真实价格、自动换仓和忽略换仓信号计算等参数。
2. 价格比率计算:在每个Bar上,计算两个品种的价格比率,并根据设定的斜率计算长度计算其斜率。
3. 趋势判断:通过比较当前价格比率和近期最高/最低值,判断价格比率是否创近期新高或新低,从而确定市场趋势。
4. 开仓条件:根据市场趋势和斜率变化,确定多空开仓条件。例如,当价格比率斜率上升且创近期新高时,进行多头开仓;当价格比率斜率下降且创近期新低时,进行空头开仓。
5. 出场条件:通过设定吊顶出场回撤系数,计算出场价格。当价格比率回落至设定阈值时,平仓出场,以控制风险。
交易逻辑详细说明
数据准备
在策略的初始化阶段,通过`OnInit()`函数设置了一系列数据预处理参数,包括后复权、映射真实价格、自动换仓和忽略换仓信号计算等。这些设置确保了后续计算和分析基于准确和完整的数据。
价格比率和斜率计算
在每个Bar上,策略首先计算两个品种的价格比率(`price_ratio`),即品种1的收盘价除以品种2的收盘价。然后,使用线性回归斜率函数(`LinearRegSlope`)计算价格比率的斜率(`slope_pr`),并设定一个价格比回溯长度(`PrLength`),用于计算价格比率的近期最高值(`highest_pr`)和最低值(`lowest_pr`)。
趋势判断
接下来,策略通过比较当前价格比率和近期最高/最低值,判断价格比率是否创近期新高或新低。具体来说,如果当前价格比率的斜率大于前一时刻的斜率,则认为价格比率斜率上升(`cond_slope_up`);
反之,则认为价格比率斜率下降(`cond_slope_dn`)。同时,如果当前价格比率超过近期最高值,则认为价格比率创近期新高(`cond_over`);如果当前价格比率低于近期最低值,则认为价格比率创近期新低(`cond_under`)。
开仓条件
根据市场趋势和斜率变化,策略确定了多空开仓条件。
对于品种1,当价格比率斜率上升且创近期新高时,满足多头开仓条件,策略会根据设定资金量计算开仓手数,并按当前开盘价买入相应数量的多头仓位。
对于品种2,交易逻辑与品种1相反,当价格比率斜率上升且创近期新高时,满足空头开仓条件,策略会按当前开盘价卖出相应数量的空头仓位。
出场条件
为了控制风险,策略设定了吊顶出场回撤系数(`StopThre`),并根据当前价格比率和近期最高/最低值计算出场价格。
具体来说,对于多头仓位,策略会记录入场后的最高价格比率(`highest_pr_after_entry`),并计算出场价格(`stop_price`)为最高价格比率减去回撤系数乘以当前价格比率的变化百分比。
当价格比率回落至出场价格时,策略会平仓出场。对于空头仓位,逻辑类似,但出场价格为最低价格比率加上回撤系数乘以当前价格比率的变化百分比。
特点总结
- 多空双向交易:策略支持两个品种的多空双向交易,能够灵活应对市场上涨和下跌趋势。
- 动态调整:通过实时计算价格比率和斜率,策略能够动态调整交易方向和仓位,适应市场变化。
- 风险管理:利用设定的保证金比例和资金量计算开仓手数,并通过吊顶出场方式控制风险,确保交易的安全性和稳定性。
- 简单直观:策略逻辑清晰,易于理解和实现,适合不同水平的交易者使用。
一种基于价格比率和斜率变化的交易策略,通过多空双向交易和动态调整,结合严格的风险管理措施,旨在实现稳定的投资回报。
策略思维导图:
策略代码(TBQ版本):
Params
Numeric Cash(50000); //双边保证金,单位:元。例如设为5w,则多头2.5w,空头2.5w。
Numeric MRate(10); //保证金比例,单位:%,百分比
Numeric SlopeLength(20); //斜率计算长度
Numeric PrLength(10); //价格比回溯长度
Numeric StopThre(5); //吊顶出场回撤系数,单位:%,百分比
Vars
Numeric lots;
Series<Numeric> price_ratio;
Series<Numeric> slope_pr;
Series<Numeric> highest_pr;
Series<Numeric> lowest_pr;
Series<Numeric> highest_pr_after_entry;
Series<Numeric> lowest_pr_after_entry;
Series<Numeric> stop_price;
Series<Bool> cond_slope_up;
Series<Bool> cond_slope_dn;
Series<Bool> cond_pr_up;
Series<Bool> cond_pr_dn;
Series<Bool> cond_over;
Series<Bool> cond_under;
Events
OnInit()
{
Range[0:DataCount-1]
{
AddDataFlag(Enum_Data_RolloverBackWard()); //设置后复权
AddDataFlag(Enum_Data_RolloverRealPrice()); //设置映射真实价格
AddDataFlag(Enum_Data_AutoSwapPosition()); //设置自动换仓
AddDataFlag(Enum_Data_IgnoreSwapSignalCalc()); //设置忽略换仓信号计算
}
}
OnBar(ArrayRef<Integer> indexs)
{
// 两个品种公共计算部分
Range[0:1]
{
// 两个品种的价格比(价比)
price_ratio = Data0.Close / Data1.Close;
// 价比的斜率
slope_pr = 100 * LinearRegSlope(price_ratio, SlopeLength);
// 价比近期最大值/最小值
highest_pr = Highest(price_ratio, PrLength);
lowest_pr = Lowest(price_ratio, PrLength);
// 价比斜率放大
cond_slope_up = slope_pr > slope_pr[1];
// 价比斜率缩小
cond_slope_dn = slope_pr < slope_pr[1];
// 价比创近期新高
cond_over = CrossOver(price_ratio, highest_pr[1]) ;
// 价比创近期新低
cond_under = CrossUnder(price_ratio, lowest_pr[1]) ;
}
// 品种1
Range[0:0]
{
// 多头开仓
if(MarketPosition == 0 and cond_slope_up[1] and cond_over[1])
{
// 根据设定资金量计算开仓手数(按真实价格计算)
lots = Max(1, IntPart(0.5 * Cash / (Open / Rollover * ContractUnit * BigPointValue * MRate / 100.0)));
Buy(lots, Open);
highest_pr_after_entry = price_ratio;
}
// 多头仓位吊顶出场
if(MarketPosition > 0)
{
highest_pr_after_entry = Max(highest_pr_after_entry, price_ratio);
stop_price = highest_pr_after_entry - StopThre * price_ratio[1] / 100.0;
if(BarsSinceEntry > 0 and price_ratio[1] < stop_price[1])
{
Sell(0, Open);
}
}
// 空头开仓
if (MarketPosition == 0 and cond_slope_dn[1] and cond_under[1])
{
// 根据设定资金量计算开仓手数(按真实价格计算)
lots = Max(1, IntPart(0.5 * Cash / (Open / Rollover * ContractUnit * BigPointValue * MRate / 100.0)));
SellShort(lots, Open);
lowest_pr_after_entry = price_ratio;
}
// 空头仓位吊顶出场
if(MarketPosition < 0)
{
lowest_pr_after_entry = Min(lowest_pr_after_entry, price_ratio);
stop_price = lowest_pr_after_entry + StopThre * price_ratio[1] / 100.0;
if(BarsSinceEntry > 0 and price_ratio[1] > stop_price[1])
{
BuyToCover(0, Open);
}
}
}
// 品种2,交易逻辑与品种1相反
Range[1:1]
{
// 空头开仓
if(MarketPosition == 0 and cond_slope_up[1] and cond_over[1])
{
// 根据设定资金量计算开仓手数(按真实价格计算)
lots = Max(1, IntPart(0.5 * Cash / (Open / Rollover * ContractUnit * BigPointValue * MRate / 100.0)));
SellShort(lots, Open);
highest_pr_after_entry = price_ratio;
}
// 空头仓位吊顶出场
if(MarketPosition < 0)
{
highest_pr_after_entry = Max(highest_pr_after_entry, price_ratio);
stop_price = highest_pr_after_entry - StopThre * price_ratio[1] / 100.0;
if(BarsSinceEntry > 0 and price_ratio[1] < stop_price[1])
{
BuyToCover(0, Open);
}
}
// 多头开仓
if (MarketPosition == 0 and cond_slope_dn[1] and cond_under[1])
{
// 根据设定资金量计算开仓手数(按真实价格计算)
lots = Max(1, IntPart(0.5 * Cash / (Open / Rollover * ContractUnit * BigPointValue * MRate / 100.0)));
Buy(lots, Open);
lowest_pr_after_entry = price_ratio;
}
// 多头仓位吊顶出场
if(MarketPosition > 0)
{
lowest_pr_after_entry = Min(lowest_pr_after_entry, price_ratio);
stop_price = lowest_pr_after_entry + StopThre * price_ratio[1] / 100.0;
if(BarsSinceEntry > 0 and price_ratio[1] > stop_price[1])
{
Sell(0, Open);
}
}
}
}