线性EA变幂系统实战教程
用固定分数仓位管理提升MQL5交易系统收益
一、什么是线性交易系统与幂交易系统
在MQL5社区语境中,线性交易系统是指那些在一段时间内使用固定手数、其资产净值曲线近似呈现直线上升或平稳形态的策略EA。这类系统经过历史验证能够盈利,但资金增长受限于固定仓位,无法随账户膨胀而加速。幂交易系统(又称指数化系统)则通过仓位规模与账户净值成比例变动的资金管理模型,使净值曲线呈抛物线或指数形态增长。本文所说的“取幂”并非数学严格幂运算,而是指让下单规模适应风险、以几何级数放大收益的资金管理思想。
将线性系统提升为幂系统的核心价值在于:在不改变原交易信号逻辑的前提下,仅替换资金管理模块,就可能让同样胜率的策略在复利效应下获得更高绝对收益。但必须强调,这种提升依赖于原系统本身是正期望的,若原系统亏损,指数化只会加速破产。
二、常见资金管理模型对比
资金管理模型是交易者关于仓位规模、止损设置、预付款与交易成本决策的框架。经典模型包括固定手数、固定分数、固定比率、Kelly百分比以及实际成本法等。固定手数最简单,每单相同手数,净值曲线线性;固定分数让每笔风险为净值的固定比例;固定比率由Ryan Jones提出,以每笔盈利增加合约;Kelly根据胜率与赔率计算最优下注比例;实际成本法考虑点差佣金后定仓。本文专注固定分数的一种MQL5变体。
- 固定手数:实现简单,但大账户资金利用率低,小账户易爆仓
- 固定分数:破产风险理论为零,规模随净值比例调整,适合中等频率策略
- 固定比率:更适合连续盈利后扩仓,对连亏恢复慢
- Kelly:理论上增长最快,但波动剧烈,实战常折半使用
- 实际成本:最贴近真实市场摩擦,但计算复杂
三、固定分数模型原理与公式
固定分数仓位规模的核心思想是根据预估风险对操作分级,每笔交易风险占净值的相同百分比。基础方程:N = f * Equity / Trade Risk。其中N为合约数量,f为固定分数(0到1之间),Equity为当前账户净值,Trade Risk为单合约风险金额(如止损距离换算的金钱损失)。该模型有趣属性是:因规模与余额成比例,理论上不会亏光,破产风险为零;但低比例下连赢连输对曲线影响温和。
在MQL5实现中,我们采用变体:净值增长到所谓“水平十”前指数扩大,之后转线性,但始终保持仓位与净值曲线比例增大的基本理念。这避免了极端复利在实盘因手数离散无法执行的尴尬。
四、获取并审视你的线性交易系统
升级前需一个已验证的线性系统作为“幂底”。例如代码库HawaiianTsunamiSurfer在2012年1至3月净值近似直线。本文不从头开发信号,而是假设你已用面向对象范式写出类似EA。若尚未掌握OOP,应先读《另一个MQL5 OOP类》《建立自动新闻交易者》打下基础。你的系统应有状态管理、信号判断与下单模块,我们将注入资金管理层。
五、CEvolution类:面向对象资金管理中心
我们沿用之前文章的CExpansion设计,新增CEvolution类追踪临时信息并实现资金逻辑。因固定分数风险比例随净值变化,仓位可变,故逻辑必须置于CEvolution内。类保护成员含m_status(EA状态)、m_expEquityLevel(指数净值级别枚举)、m_originalEquity(初始净值)、m_lotSize(当前手数)。构造时记录原始净值:m_originalEquity=AccountInfoDouble(ACCOUNT_EQUITY)。
CalcEquityGrowth计算相对原始净值的增长百分比:return NormalizeDouble(currentEquity*100/m_originalEquity-100,2)。RefreshExpEquityLevel依增长刷新级别(LEVEL_ONE至LEVEL_TEN),RefreshLotSize依级别刷新手数。级别枚举如下:
enum ENUM_EXP_EQUITY_CURVE_LEVEL
{
LEVEL_ONE,
LEVEL_TWO,
LEVEL_THREE,
LEVEL_FOUR,
LEVEL_FIVE,
LEVEL_SIX,
LEVEL_SEVEN,
LEVEL_EIGHT,
LEVEL_NINE,
LEVEL_TEN
};
类头文件节选展示结构:
class CEvolution
{
protected:
ENUM_STATUS_EA m_status;
ENUM_EXP_EQUITY_CURVE_LEVEL m_expEquityLevel;
double m_originalEquity;
double m_lotSize;
public:
CEvolution(ENUM_STATUS_EA status,ENUM_EXP_EQUITY_CURVE_LEVEL exp_equity_level);
~CEvolution(void);
ENUM_STATUS_EA GetStatus(void);
double GetLotSize(void);
double CalcEquityGrowth(double currentEquity);
void RefreshExpEquityLevel(double currentEquity);
void RefreshLotSize();
};
构造函数示例:
CEvolution::CEvolution(ENUM_STATUS_EA status,ENUM_EXP_EQUITY_CURVE_LEVEL exp_equity_level)
{
m_status=status;
m_expEquityLevel=exp_equity_level;
RefreshLotSize();
m_originalEquity=AccountInfoDouble(ACCOUNT_EQUITY);
}
增长计算方法:
double CEvolution::CalcEquityGrowth(double currentEquity)
{
return NormalizeDouble(currentEquity * 100 / m_originalEquity - 100,2);
}
六、在EA中集成与调用幂逻辑
在EA的OnTick中,先刷新进化对象再下单。典型调用:
GetEvolution().RefreshExpEquityLevel(AccountInfoDouble(ACCOUNT_EQUITY)); GetEvolution().RefreshLotSize();
下单时用手数获取方法替代固定值,例如:
switch(GetEvolution().GetStatus())
{
case BUY:
tp = ask + m_takeProfit * _Point;
sl = bid - m_stopLoss * _Point;
GetTrade().PositionOpen(GetBrain().GetSymbol(),ORDER_TYPE_BUY,m_evolution.GetLotSize(),ask,sl,tp);
break;
case SELL:
sl = ask + m_takeProfit * _Point;
tp = bid - m_stopLoss * _Point;
GetTrade().PositionOpen(GetBrain().GetSymbol(),ORDER_TYPE_SELL,m_evolution.GetLotSize(),bid,sl,tp);
break;
case DO_NOTHING:
break;
}
我们将指数化系统重命名为ExponentialHawaiian,以区分原线性版本。注意手数需经NormalizeDouble与经纪商最小手数对齐,否则OrderSend报错。
七、回测验证与稳定性边界
添加OO逻辑后必须回测。ExponentialHawaiian在2012年1-3月净值曲线呈指数,原系统线性。关键警告:当指数条件不再成立(如曲线转跌或震荡),系统不稳定,理论破产风险再现。因此实盘需监控净值级别,若跌破LEVEL_ONE应考虑暂停或降f值。
八、与其他方案及社区争议的思考
社区用户GaryKa指出:对价格图表非线性缩放终归头寸管理,但市场离散使长期退化线性。Yury Reshetov强调Vince非实战家,Thorp的Kelly实践更可靠,固定分数非普适。我们认同:本文提供的是工具而非圣杯。若原系统期望为负,任何幂化加速死亡。建议读者结合自己系统测试,而非盲目崇拜理论。
对比直接改手数公式的面向过程写法,OO的CEvolution优势在状态封装、易扩展(如加LEVEL_ELEVEN)、与现有Brain/Trade类解耦。若你系统非OO,可提取函数但不如重构优雅。
九、部署检查清单与结语
- 确认原线性EA正期望且OOP结构清晰
- 包含Enums.mqh定义状态与级别枚举
- CEvolution构造记录原始净值,OnTick刷新级别与手数
- 下单调用GetLotSize并校验最小手数
- 策略测试器多周期回测,观察指数边界
- 实盘前用模拟账户验证手数随净值变化逻辑
今天我们学会通过固定分数变体将线性系统升级为幂系统。再次提醒:先读OOP基础文章,严格测试。资金管理放大的是概率优势,而非创造优势。愿你的净值曲线优雅向上。