外汇交易的基础数学(基础篇)
「点值、杠杆与保证金的真实换算」
在 MT5 里做外汇或贵金属,先要搞清楚每动一个点账户会怎样。以标准账户 EURUSD 为例,1 手合约 = 100 000 单位基础货币,价格每波动 1 点(0.0001)对应 10 美元浮盈浮亏;若做 0.1 手,则每点 1 美元。这个数字是仓位管理的底线,不是参考。 杠杆只是放大可用保证金的工具。用 1:100 杠杆开 1 手 EURUSD,所需保证金约为合约价值 / 100 = 1000 美元(按当时汇率折算)。MT5 会在「交易」面板实时显示占用保证金与可用预付款,当可用预付款低于保证金要求,平台会强制平仓。外汇与贵金属属高波动品种,杠杆会同步放大穿仓概率。 很多人误以为「点值固定」,其实交叉盘和黄金的点值随报价变。XAUUSD 1 手每波动 1 美元(报价小数点后一位)约 100 美元,但报价精度与合约规模会在券商间有差异,开仓前应在 MT5 的「规格」里核对合约大小与计算模式。
◍ 从五年实盘开发看市场底层逻辑
我做了五年以上的自动交易策略和软件交付,MT5 上跑过的 EA 和指标不算少。这篇不打算讲术语堆砌,而是把刚进场的人和已经盯盘几年的老手都拉到同一条线上:用可复现的代码现象看价格到底怎么动。 有些思路已经做成了对外发布的机器人和指标,但那只是我整个策略库里很小的一块。真正值得说的,是我用大量不同逻辑 EA 在 EURUSD、XAUUSD 上回测后,看到的那些反复出现的市况特征。 外汇和贵金属杠杆高、滑点跳空频繁,任何从代码里看到的规律都只是概率倾向,不是必然。后面几节会直接贴 MQL5 片段,你可以自己开 MT5 把参数改掉验证。
为什么出入场点总是慢半拍
要是能精准锁定进场和离场位置,交易里大半难题都消失了。可现实里这两个点极难捕捉,表面看一段行情总能归纳出某个形态并顺着走一阵,但真要脱离高级工具和指标去提前识别,基本做不到。 最直白且反复出现的两种结构就是趋势和横盘:趋势是朝一个方向的长周期推进,横盘则是反转更密集的震荡区。靠肉眼不用任何指标也能认出它们,问题在于——形态都是走出来以后才被你看见,触发之前你根本不在局内。 更麻烦的是,没有任何形态能打包票。无论用何种策略,都不存在某种模式能确保你的账户不被清零,外汇和贵金属这种高杠杆市场里,错一次就可能吞掉前面十次的对。后面我会用数理语言拆一下背后可能的机理。
「市价与限价如何撑起市场深度」
市场价格变动的真正推手只有两类订单:市价单与限价单。限价买卖盘堆出市场深度——一条垂直价格尺,标出愿意成交的价位。买方限价单永远沉在底部,卖方限价单永远挂在顶部,两者之间留出的空隙就是点差,用最小价格变动单位计量。 点差即最优买价与最优卖价的距离。市价单进来吃单,限价单被触发,深度结构随之改写。活跃市价单常带止损与获利,这些仓位分散在市场各处,构成潜在的加速或反转水平;价格能否突破,取决于止损单的数量、类型与交易量。 限价单还会在关键价位(如日线或周线开盘价)聚成难以穿透的集群。谈“基于水平的交易”时,交易员指的就是这些限价层。打开 MT5 市场深度窗口(右键图表—市场深度),能直接看到买卖盘与点差实时分布。
◍ 用概率方程拆穿随机市场的零收益真相
MT5 报价窗里看到的价格,本质是时间参数 t 的离散函数:tick 是最小不可再分的报价点,往上才是柱、M1/M5 烛形。市场混杂随机与模式因素,但大环境概率化且近不可预测,理解它得靠概率论,而引入概率密度前必须先做离散化。 先把「事件」钉死:C1=获利(触 tp),C2=止损(触 sl),二者穷尽互斥,故 P1+P2=1。若用随机开仓+随机 tp/sl 测 EA 或手工策略,结果恒随机,预期收益 M = P1*tp - P2*sl;无序市场里该式等于 0(点差设 0 时),说明乱做无论止损怎么摆都是零期望。 推广到含信号平仓的策略,引入 C3(止损平)、C4(信号平),有 M = P3*M3 + (1-P3)*M4,其中 M3 为触损期望、M4 为信号平期望。P1/P2/P0[i]/P01[j] 在此变条件概率,严格走全概率(贝叶斯)公式;完全无序时仍 M=0。再铺开 N 个止损档位:M = Σ PS[k]*MS[k],每层 MS[k] 又嵌套 M3[k] 与 M4[k]。破零均衡的唯一办法,是摸清固定区间或时段内各方向运动概率——选对出入场点才可能有正期望。 利润因子 PF = Mp/Ml,>1 才盈利。Mp 只装利润项(M3p[k]=P1[k]*tp[k],M4p[k]=ΣP0[i][k]*pr[i][k]),Ml 只装亏损项(M3l[k]=(1-P1[k])*sl[k],M4l[k]=ΣP01[j][k]*ls[j][k])。无序无点差时 PF=1,M 与 PF 已足够从两侧评估策略。 用固定步长 H 离散价格:n 总步、u 升步、d 降步、s=u-d 净向步。解 n=u+d 与 s=u-d 得 u=(s+n)/2、d=n-u;s 间距恒为 2 才能保证 u/d 自然数可算组合。总选项 2^n,同 s 的组合数 C=n!/(u!*d!),单场景概率 P=C/(2^n),求和必为 1。以此建概率密度图,偶数 n 从 0 起节点、奇数 n 从 1 起,负 s 镜像处理。
| 趋势还是横盘用量化比:K=ΣP[i]* | s[i] | 为均衡比,Kp>K 倾向趋势市、Kp<K 倾向横盘;KMid 分界算 KTrendPercent 与 KFletPercent。另一比 T=ΣP[i]*s[i] 是阿尔法趋势指标,T>0 可能买趋、T<0 可能卖趋、T=0 即随机游走,APercent=(T/TMax)*100 正牛负熊。步数一变参考分布就得重算,这些方程可直接塞进 EA 或指标。外汇与贵金属属高风险品种,上述概率模型仅描述历史结构,实盘信号仍可能失效。 |
|---|
把离散概率研究压成一个可移植指标
做这个指标的目的很直接:把前面那套市场步长离散分布的数学,变成 MT5 里能加载、能看、还能当 EA 原型的东西。代码层面刻意写得接近 MQL4 语法,只在必须处用 MQL5 数组接口,这样后续迁回 MT4 基本是复制粘贴。视觉上只留中性分布线和实时分布线,不堆面板按钮,避免遮挡价格本身。 输入参数先定死边界:分析 990 根 Bars、内存存 2000 步、公式用 40 步、每步 30 点、默认画步长。这些数不是拍脑袋,步长 30 点在 EURUSD 这类品种大约对应 3 个标准点差,40 步覆盖约 1200 点路径,对日内波段够用,外汇和贵金属波动大,实盘前务必自己改参数回看。 柱数据访问用一组兼容数组(Close/Open/High/Low/Volume/Time)加 DimensionAllMQL5Values() 设大小、CalcAllMQL5Values() 刷值,逻辑和 MQL4 的数组遍历一致。节点结构存自身与落在其上的步、活跃布尔量;只有节点内存被实节点填满才算真实分布,没步就不算,省掉空转。 概率纵坐标按「某结果出现次数 / 总结果数」直接除出来,不叫正态密度而叫离散概率,因为本身是分桶图不是连续函数。alpha 与 betta 趋势百分比算完钉在左上角,其余绘图函数放附件,主文件只留核心缓冲 CurrentBuffer 与 NeutralBuffer,最近一根烛形上逐柱标概率,缩放图表就能读全。
input class="type">uint BarsI=class="num">990;class=class="str">"cmt">//Bars TO Analyse( start calc. & drawing ) input class="type">uint StepsMemoryI=class="num">2000;class=class="str">"cmt">//Steps In Memory input class="type">uint StepsI=class="num">40;class=class="str">"cmt">//Formula Steps input class="type">uint StepPoints=class="num">30;class=class="str">"cmt">//Step Value input class="type">bool bDrawE=true;class=class="str">"cmt">//Draw Steps class=class="str">"cmt">//variable to be moved in MQL5 class="type">class="kw">double Close[]; class="type">class="kw">double Open[]; class="type">class="kw">double High[]; class="type">class="kw">double Low[]; class="type">long Volume[]; class="type">class="kw">datetime Time[]; class="type">class="kw">double Bid; class="type">class="kw">double Ask; class="type">class="kw">double Point=_Point; class="type">int Bars=class="num">1000; class="type">MqlTick TickAlphaPsi; class="type">void DimensionAllMQL5Values()class=class="str">"cmt">//set the necessary array size { ArrayResize(Close,BarsI,class="num">0); ArrayResize(Open,BarsI,class="num">0); ArrayResize(Time,BarsI,class="num">0); ArrayResize(High,BarsI,class="num">0); ArrayResize(Low,BarsI,class="num">0); ArrayResize(Volume,BarsI,class="num">0); } class="type">void CalcAllMQL5Values()class=class="str">"cmt">//recalculate all arrays { ArraySetAsSeries(Close,false); ArraySetAsSeries(Open,false); ArraySetAsSeries(High,false); ArraySetAsSeries(Low,false); ArraySetAsSeries(Volume,false); ArraySetAsSeries(Time,false); if( Bars >= class="type">int(BarsI) ) { CopyClose(_Symbol,_Period,class="num">0,BarsI,Close); CopyOpen(_Symbol,_Period,class="num">0,BarsI,Open);