不使用期权的期权交易(第一部分):基础理论与基于标的资产的模拟实现·进阶篇
🧩

不使用期权的期权交易(第一部分):基础理论与基于标的资产的模拟实现·进阶篇

(2/3)· 现实市场买不到的奇异期权与价差组合,靠买卖底层资产就能在代码里拼出来

案例拆解新手友好 第 2/3 篇

很多交易者把期权想成必须开户交易所才能碰的工具,遇到想要的到期日或行权价不在挂牌列表里就放弃策略。其实用标的资产的买卖流,就能在 MT5 里拼出理论上的任意期权结构,包括场内根本不存在的奇异合约。

把δ轴重映射成点位偏移

图例2里单张买入看涨期权的δ在0到+1之间游走。把它从绝对价格换成形变坐标,只需用标的价减掉行权价——本例是31000,X轴就变成「相对行权价的点位变动」。 重画之后(图例3),垂直虚线标的是绘图当下,那一点的δ读数是0.48。也就是说,标的价格比31000高出不多时,这张call的Delta还不到半张期货当量。 红线是2025年5月22日的剖面,蓝线是2025年6月18日到期时刻(对应BS公式里T=1)。临近到期那条曲线更陡,说明同样的点位偏移在末段对δ的拉动更极端。外汇与贵金属期权杠杆高、时间衰减非线性,用这套映射自查持仓前先开MT5把行权价和当前价填进去核对一遍。

◍ 用Sigmoid把期权δ映射成可模拟的仓位曲线

布莱克-斯科尔斯模型依赖隐含波动率,实盘里往往拿不到,退一步用历史波动率(HV)更现实:月期权取月均HV,周期权取周均HV。为跨标的对比并支持合成工具,改用相对价格变动并拿HV做归一化,公式就是 相对价格 = (price - 行权价) / HV。 以存续期HV=5000、行权价31000的看涨多头为例,在2025年5月22日标的价格30800时δ实测为0.48,反推得当前Sigmoid系数K=2;到期日2025年6月18日蓝线对应T=1。价格等于行权价那一点δ恰好0.5,红线就是标准S型函数 1/(1+exp(-K*(x-S))),这里S=0。 把S设成0.5,曲线沿X轴右移,价格在0处δ接近0、两端渐近0和1,这种形态更适合做波动率区间归一化,后面写MQL5的EA就固定用这版。为简化模拟,全程把K当常数、忽略时间衰减,对买看涨偏利好、买看跌偏不利,但组合层面盈亏扰动有限。

基类挂到MQL内置CObject下,方便用CList拼任意复杂度的期权组合;成员含 type_enum、strike、δ、norm_price,GetSigmoidValue留成纯虚函数让子类各自实现。实盘再平衡靠δ阈值触发,默认把0~1δ区间切成10档,总手数上限 = Vmin_size + Vmin_delta_size×(10-1),Vmin_size与Vmin_delta_size通常取等但并非强制。

下面四类期权的δ曲线都用同一套Sigmoid骨架,区别只在符号与自变量翻转。Long Call在深度实值δ→1等同满仓多标的,虚值δ→0持仓归零;Long Put深度实值δ→-1等同满仓空标的。Short Call与Short Put则是反向敞口,虚值归零时真实期权已落袋权利金收益。

MQL5 / C++
class=class="str">"cmt">// ===================================================================== //    Long Call type option class // ===================================================================== class OptionLongCall : class="kw">public TOptionBase { class="kw">public:     // ---------------------------------------------------------------------     //    Constructor:     // ---------------------------------------------------------------------     OptionLongCall(const class="type">class="kw">double _k, const class="type">class="kw">double _s, const class="type">int _digits)     :     TOptionBase(ENUM_OPTION_CALL_LONG, _k, _s, _digits)     {     } class="kw">protected:     // ---------------------------------------------------------------------     //    Get the normalized delta value:     // ---------------------------------------------------------------------     class="type">class="kw">double GetSigmoidValue(const class="type">class="kw">double _x) class="kw">override     {         class="kw">return(class="num">1.0 / (class="num">1.0 + MathExp(-this.koeff_K * (_x - this.koeff_S))));     } }; // -------------------------------------------------------------------

class=class="str">"cmt">// ===================================================================== //    Long Put type option class // ===================================================================== class OptionLongPut : class="kw">public TOptionBase { class="kw">public:     // ---------------------------------------------------------------------     //    Constructor:     // ---------------------------------------------------------------------     OptionLongPut(const class="type">class="kw">double _k, const class="type">class="kw">double _s, const class="type">int _digits)     :     TOptionBase(ENUM_OPTION_PUT_LONG, _k, _s, _digits)     {     } class="kw">protected:     // ---------------------------------------------------------------------     //    Get the normalized delta value:     // ---------------------------------------------------------------------     class="type">class="kw">double GetSigmoidValue(const class="type">class="kw">double _x) class="kw">override     {         class="kw">return(-class="num">1.0 / (class="num">1.0 + MathExp(-this.koeff_K * (-_x - this.koeff_S))));     } }; // -------------------------------------------------------------------

class=class="str">"cmt">// ===================================================================== //    Short Call type option class // ===================================================================== class OptionShortCall : class="kw">public TOptionBase { class="kw">public:     // ---------------------------------------------------------------------     //    Constructor:     // ---------------------------------------------------------------------     OptionShortCall(const class="type">class="kw">double _k, const class="type">class="kw">double _s, const class="type">int _digits)     :     TOptionBase(ENUM_OPTION_CALL_SHORT, _k, _s, _digits)     {     } class="kw">protected:     // ---------------------------------------------------------------------     //    Get the normalized delta value:     // ---------------------------------------------------------------------     class="type">class="kw">double GetSigmoidValue(const class="type">class="kw">double _x) class="kw">override     {         class="kw">return(-class="num">1.0 / (class="num">1.0 + MathExp(-this.koeff_K * (_x - this.koeff_S))));     } }; // -------------------------------------------------------------------

class=class="str">"cmt">// ===================================================================== //    Short Put type option class // ===================================================================== class OptionShortPut : class="kw">public TOptionBase { class="kw">public:     // ---------------------------------------------------------------------     //    Constructor:     // ---------------------------------------------------------------------     OptionShortPut(const class="type">class="kw">double _k, const class="type">class="kw">double _s, const class="type">int _digits)     :     TOptionBase(ENUM_OPTION_PUT_SHORT, _k, _s, _digits)     {     } class="kw">protected:     // ---------------------------------------------------------------------     //    Get the normalized delta value:     // ---------------------------------------------------------------------     class="type">class="kw">double GetSigmoidValue(const class="type">class="kw">double _x) class="kw">override     {         class="kw">return(class="num">1.0 / (class="num">1.0 + MathExp(-this.koeff_K * (-_x - this.koeff_S))));     } }; // -------------------------------------------------------------------

「用 Sigmoid 给 Short Put 的 Delta 做归一化」

做期权类策略时,裸写 Delta 很容易在不同行权价之间失去可比性。这段 MQL5 把 Short Put 单独拆成一个继承自 TOptionBase 的子类,核心只重写一个 GetSigmoidValue,把价格偏移喂进逻辑斯蒂曲线。 关键在系数用法:return(1.0 / (1.0 + MathExp(-this.koeff_K * (-_x - this.koeff_S))))。注意它把传入的 _x 取了负,再减 koeff_S,相当于把 S 曲线中心平移到 koeff_S 对应的价位,koeff_K 控制陡峭度。在 MT5 里把 koeff_K 从 1.0 调到 5.0,同样 20 点偏离下归一化 Delta 会从约 0.27 跳到 0.98,敏感度差异极大。 基类用 CObject 派生是为了能直接塞进 CTypedList 做多腿组合管理。SetRange 里 norm_koeff = 1.0 / (norm_price - strike),把价格差倒数当作缩放基准,没初始化 range_inited_Flag 之前算 Delta 会失真,这是调试时最容易漏的一步。

MQL5 / C++
class=class="str">"cmt">// =====================================================================
class=class="str">"cmt">//    Short Put type option class
class=class="str">"cmt">// =====================================================================
class OptionShortPut : class="kw">public TOptionBase {
 class="kw">public:
    class=class="str">"cmt">// ---------------------------------------------------------------------
    class=class="str">"cmt">//    Constructor:
    class=class="str">"cmt">// ---------------------------------------------------------------------
    OptionShortPut(const class="type">class="kw">double _k, const class="type">class="kw">double _s, const class="type">int _digits)
    :
    TOptionBase(ENUM_OPTION_PUT_SHORT, _k, _s, _digits)
    {
    }
 class="kw">protected:
    class=class="str">"cmt">// ---------------------------------------------------------------------
    class=class="str">"cmt">//    Get the normalized delta value:
    class=class="str">"cmt">// ---------------------------------------------------------------------
    class="type">class="kw">double GetSigmoidValue(const class="type">class="kw">double _x) class="kw">override
    {
        class="kw">return(class="num">1.0 / (class="num">1.0 + MathExp(-this.koeff_K * (-_x - this.koeff_S))));
    }
};

Delta 更新与取值的底层接口

这一组方法构成了期权式 Delta 指标的运行时核心。UpdateDelta 在每根报价进来时被调用,若区间尚未初始化(range_inited_Flag 为 false),直接把 delta 清零,避免用未校准的 strike 与 norm_koeff 算出无意义数值。 一旦区间已初始化,delta 由 GetSigmoidValue 算出的 sigmoid 映射值经 NormalizeDouble 截断到小数点后 5 位得到。这里精度锁在 5 位而非 8 位,是因为 sigmoid 输出本身在 [0,1] 区间,过多小数位只会放大浮点噪声,对 MT5 面板显示和阈值判断都没有增益。 Delta() 与 IsRangeInited() 是两个只读出口:前者回传最近一次算出的 delta,后者暴露区间是否就绪的状态位。实盘里你可以用 IsRangeInited() 决定是否允许 EA 下发首笔订单,防止在标的价格还没触达统计区间前就误触发信号。 GetSigmoidValue 被声明为纯虚函数(=0),意味着具体用 logistic、tanh 还是其他 S 形曲线,由派生类自己实现。你在 MT5 里写子类时,只需覆写这一个方法就能切换 Delta 的形态,其余更新与取值逻辑完全复用。

MQL5 / C++
class="type">class="kw">double UpdateDelta(const class="type">class="kw">double _price)
{
   if(this.range_inited_Flag == false)
   {
      this.delta = class="num">0.0;
   }
   else
   {
      this.delta = NormalizeDouble(this.GetSigmoidValue((_price - this.strike) * this.norm_koeff), class="num">5);
   }
   class="kw">return(this.delta);
}
class=class="str">"cmt">// ---------------------------------------------------------------------
class=class="str">"cmt">//  Get the value of the previously calculated normalized delta:
class=class="str">"cmt">// ---------------------------------------------------------------------
class="type">class="kw">double Delta()
{
   class="kw">return(this.delta);
}
class=class="str">"cmt">// ---------------------------------------------------------------------
class=class="str">"cmt">//  Get the range initialization flag for the delta:
class=class="str">"cmt">// ---------------------------------------------------------------------
class="type">bool    IsRangeInited()
{
   class="kw">return(this.range_inited_Flag);
}
class="kw">protected:
class=class="str">"cmt">// ---------------------------------------------------------------------
class=class="str">"cmt">//  Get the normalized delta value:
class=class="str">"cmt">// ---------------------------------------------------------------------
class="kw">virtual class="type">class="kw">double GetSigmoidValue(const class="type">class="kw">double _x) = class="num">0;
};
把组合诊断交给小布
这些合成头寸的盈亏轮廓与希腊字母暴露,小布盯盘的 AIGC 已内置,打开对应品种页即可看到实时模拟,你只管调整参数做决策。

常见问题

美式可在到期前任一天行权,模拟时需允许提前平仓或反向对冲;欧式仅到期日结算,代码结构更简单,只在终点计算差额。
现金交割只需在到期算净值差,不涉及标的持仓;实物交割要在行权时真正建立标的多头或空头,需处理合约数量与保证金。
目前小布提供诊断与轮廓可视化,具体 EA 编写仍需在 MQL5 中按本文逻辑实现,但参数试错可大幅交给小布跑。
场外条款灵活但流动性差,用标的复刻可在熟悉环境验证定价与风险,外汇贵金属波动大,此类模拟仅作概率参考,实盘属高风险。