外汇套利交易:一款轻松上手的简单合成做市商机器人
引言:从散户交易者到具备机构思维
经常有人问我,我是如何开发出TrisWeb_Optimized的。故事要从2016年说起,那时我初次踏入外汇世界,带着新手的天真和对指标交易的笃信。当时,我仍坚信交易存在“圣杯”——一种据说能将1000美元在一年内变成百万美元的神奇指标组合。
2017年,我的思维发生了革命性的转变。在一系列惨痛的亏损之后,我开始研究大机构实际的交易方式。我所说的并非那些在YouTube上大谈“百万美元收益”的人,而是真正的机构——银行、对冲基金和自营交易公司。
我发现:他们并不使用那些花哨的指标策略。他们运用数学原理、风险管理、套利、做市以及其他基于对市场机制深刻理解的方法。就在那时,我做出了决定:要么像大机构一样交易,要么干脆不交易。
接下来的三年时间里,我潜心研究机构交易方法。我沉浸在跨市场相关性、统计套利和算法交易的世界中。我尝试使用Python和MQL,创建了一些原型系统,这些系统模仿了大型市场参与者的方法,但针对散户交易者在资金和技术方面的限制进行了调整。
2020年1月,在金融市场历史上最为动荡的时期之一来临前夕,Tris_Optimized诞生了——这是我对“散户交易者如何应用机构策略”这一问题的回答。
这款EA并不试图预测市场走势,不依赖技术分析指标,也不需要“直觉”。相反,它通过数学计算,找出三种相关货币对之间潜在的失衡情况,并布置一系列订单,准备在失衡出现时捕捉机会。
在真实市场条件下连续运行五年多,Tris_Optimized已证明其可行性。它经历了疫情、通胀飙升、利率变动和地缘政治危机——并持续产生稳定的利润(在我真正操作交易而非通宵钻研代码构思和实际代码的少数时候)。这并非一个承诺超高回报的神奇系统,而是一款基于机构交易基本原则的既可靠又实用的工具。
如今,这种基于机构思维的交易理念,让我得以在各类市场中成功交易。近年来,我虽专注于机器学习策略,但套利方法始终是我交易策略库中的重要组成部分。将机器学习的统计方法与机构交易者所利用的基本市场模式相结合,让我获得了显著优势。我甚至受邀加入了一家鲜为人知的小型对冲基金。除了我,基金里只有一名风险经理和一名管理员,而我们正准备推出基于MetaTrader 5的对冲基金基础设施。
几周前,我在整理云存储时,偶然发现了一个存放着我旧交易机器人的存档。其中就包括Triss_Optimized,这是我的首批项目之一。尽管与现代机器学习系统相比,它显得“简单”,但仍在运行并产生收益。我在一个模拟账户上运行它,结果令人惊讶——即使没有针对当前市场条件进行优化,它也展示出了积极的结果。
于是,我决定将这段代码分享到社区。并非因为它是什么革命性的系统,能让您在一个月内成为百万富翁,而是因为这段代码是一个很好的范例,展示了作为散户交易者,如何将机构交易方法应用于交易之中。它就像一座桥梁,连接着两个世界,能帮助您完成我曾经经历过的转变。
在本文中,我将揭示TrisWeb_Optimized的运作机制,解释其架构,并分享我在设置和优化方面的经验。准备好进入专业算法交易的世界了吗?让我们开始吧。
外汇三币套利:EURUSD-GBPUSD-EURJPY三角套利
我们先从外汇三角套利说起,这简直就像一场捉鬼游戏。想象一下这样的场景:您同时监控着欧元兑美元(EURUSD)、英镑兑美元(GBPUSD)和欧元兑日元(EURJPY),试图捕捉价格短暂失衡的瞬间——即当EUR→USD→GBP→EUR的闭环交易能让您至少净赚几个点时。但事实是,纯粹的套利机会就像莫斯科市中心的独角兽一样罕见。机构凭借其高频算法和直接获取流动性的渠道,眨眼间就能将这些机会一扫而空。
正因如此,我开发了TrisWeb_Optimized——这款EA并不坐等理想条件出现,而是构建一个三维订单网络,随时准备捕捉自然市场波动带来的利润。从学术意义上讲,这并非经典的套利策略——而是一种散户交易者的游击战术,利用三种货币对之间的数学关系进行套利。
MQL5中的合成货币对:通往套利的秘密之门
什么是合成货币对?它是一种幻影,一种我们通过实际交易工具构建的数学抽象。例如,根据EURUSD和GBPUSD的报价,我们可以计算出一个合成EURGBP,理论上,这个合成汇率应与实际的EURGBP完全一致。但在现实世界中,始终存在偏差,这正是我们的“日常经历”。
TrisWeb_Optimized并未显式创建合成货币对,而是巧妙地利用了它们背后的逻辑。我们通过以下代码段获取各货币对的当前价格——这是捕捉失衡情况的第一步:
// Get the current prices for each symbol double priceSymbol1 = GetCurrentPrice(Symbol1); double priceSymbol2 = GetCurrentPrice(Symbol2); double priceSymbol3 = GetCurrentPrice(Symbol3);
这三行代码是踏入多维可能空间的入口,在那里,哪怕最细微的差异都能转化为实实在在的资金。
TrisWeb_Optimized架构:历经疫情考验的交易工具
2020年1月,当我写下TrisWeb_Optimized的第一行代码时,世界正站在疫情爆发、市场动荡和极端波动的边缘。没人能预料到,这个简单的EA竟会在几十年来最极端的市场环境中接受严峻考验。您知道结果如何吗?它居然挺过来了。不仅如此,还蓬勃发展。
系统的核心在于OnTick()函数——每当价格变动时,该函数就会被触发,同时从三个维度分析整体市场情况:
void OnTick() { // Calculate orders and profits int ordersCount1 = 0, ordersCount2 = 0, ordersCount3 = 0; double profit1 = 0, profit2 = 0, profit3 = 0; // Count pending orders CountPendingOrders(ordersCount1, ordersCount2, ordersCount3); // Calculate open positions and their profit CountOpenPositions(ordersCount1, ordersCount2, ordersCount3, profit1, profit2, profit3); // ... rest of the code }
这段代码看似平平无奇。然而,在这些代码行的背后,隐藏着一个精炼的模块化架构——系统的每个方面都被隔离成独立的功能,就像一个协调良好的有机体中的各个器官一样。没有混乱,没有无序——只有明确的职责划分。
网格参数调整:与波动性共舞
外汇市场就像一片海洋——EURUSD的走势缓慢而庄严,犹如深层的洋流;而EURJPY则可能如突如其来的海啸般剧烈波动。试图用相同的参数交易这些货币对,注定会令人失望。正因如此,TrisWeb_Optimized允许为每个交易工具自定义网格参数:
input group "Step Settings" input int Step01_Symbol1 = 40; // Initial step for Symbol1 (in points) input int Step02_Symbol1 = 60; // Step between orders for Symbol1 (in points) input int Step01_Symbol2 = 40; // Initial step for Symbol2 (in points) input int Step02_Symbol2 = 60; // Step between orders for Symbol2 (in points) input int Step01_Symbol3 = 40; // Initial step for Symbol3 (in points) input int Step02_Symbol3 = 60; // Step between orders for Symbol3 (in points)
在运用这套系统的五年时间里,我形成了一套独特的操作习惯:对于像EURUSD这样走势平稳的货币对,我采用40点和60点的标准步长;而对于波动剧烈的日元交叉盘,我会将步长增至50点和80点。这就好比根据不同鱼种调整鱼竿的灵敏度——用同样的方法,要么什么都能钓到,要么一无所获。
手数规模优化:自适应系统的核心基因
固定手数是新手才会采用的方式。资深专业人士深知:交易量必须随账户余额的变化而灵活调整。借助CalculateOptimalLotSize()函数,TrisWeb_Optimized实现了这一功能,这堪称我的得意之作:
double CalculateOptimalLotSize(string symbol, double baseSize) { if(!AutoLotOptimization) return baseSize; double accountBalance = AccountInfoDouble(ACCOUNT_BALANCE); double lotStep = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP); double minLot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN); // ... the rest of the calculation code }该功能堪称真正的瑞士军刀。它会综合考量当前账户余额、设定的风险百分比、特定交易品种的点值、经纪商对最小手数和手数增量的限制,而且——这也是我尤为自豪之处——还能针对小众货币自动调整计算方式:
// Adjustment for pairs with JPY and other exotic currencies string quoteCurrency = StringSubstr(symbol, 3, 3); if(quoteCurrency == "JPY" || quoteCurrency == "XAU" || quoteCurrency == "XAG") pointCost *= 100.0;
对于刚入行的交易者来说,日元货币对的点值是主要货币对的百分之一。如果忽略这一调整,您的交易机器人要么会以极微小的手数进行交易,要么会在一场交易中让您血本无归。
EA运行时间管理:昼夜节律算法
外汇市场全天候24小时运作,但这并不意味着您的EA也应该如此。有些时候,最好还是按兵不动——比如夜间交易时段,其点差较大且走势异常,往往带来的问题多于机会。TrisWeb_Optimized通过IsWorkTime()函数内置了“昼夜节律”机制:
bool IsWorkTime() { MqlDateTime currentTime; TimeToStruct(TimeLocal(), currentTime); datetime currentTimeSeconds = HoursMinutesToSeconds(currentTime.hour, currentTime.min); datetime startTimeSeconds = HoursMinutesToSeconds(StartTimeHour, StartTimeMin); datetime endTimeSeconds = HoursMinutesToSeconds(EndTimeHour, EndTimeMin); return (startTimeSeconds <= currentTimeSeconds && currentTimeSeconds <= endTimeSeconds); }CheckNewDayAndWorkTime()函数为这款EA赋予了另一项类似人类的特质——即具备“每日重新开始、从零做起”的能力:
void CheckNewDayAndWorkTime() { if(IsNewDay && IsNewDayReset && IsWorkTime()) { DeleteAllOrders(); IsNewDay = false; } if(!IsWorkTime()) { IsNewDay = true; } }
从长远来看,这一特性尤为宝贵——系统不会累积积压的过期订单,而是会根据当前市场状况持续更新交易网格。
平仓算法:及时离场的艺术
在交易中,正如在生活中一样,重要的不仅是在恰当的时机入场,更要在恰当的时机离场。TrisWeb_Optimized采用了一个简单而高效的平仓标准——达到既定的总盈利水平:
// Total number of orders int totalOrders = ordersCount1 + ordersCount2 + ordersCount3; double totalProfit = profit1 + profit2 + profit3; // If there are no orders, create them; if there are, check for profit. if(totalOrders == 0) { if(IsWorkTime()) { PlaceInitialOrders(); } } else if(totalProfit > Profit) { DeleteAllOrders(); }但正如人们常说——细节决定成败。该系统不仅考量“纯”利润,还会综合计算包含隔夜利息和交易佣金在内的总收益:
double swap = PositionGetDouble(POSITION_SWAP); double profit = PositionGetDouble(POSITION_PROFIT); double commission = PositionGetDouble(POSITION_COMMISSION); double totalProfitForPosition = profit + swap + commission;
这对于长期交易表现而言至关重要,尤其是当您持有头寸过夜并产生隔夜利息费用时。否则,系统可能会忽略原本盈利的交易组合,或者相反,将那些因负隔夜利息而实际亏损的组合视为盈利。
订单执行微调:与市场魔鬼的较量
在高频交易的世界里,执行质量可能决定盈亏成败。TrisWeb_Optimized采用底层MQL5结构,实现对订单下达和执行过程的极致控制:
bool OpenBuyStop(string symbol, double volume, double openPrice) { MqlTradeRequest request = {}; MqlTradeResult result = {}; request.action = TRADE_ACTION_PENDING; request.symbol = symbol; request.volume = volume; request.type = ORDER_TYPE_BUY_STOP; request.price = openPrice; request.deviation = Deviation; request.magic = EXPERT_MAGIC; if(UseCommentsInOrders) request.comment = OrderComment; if(!OrderSend(request, result)) { Print("OrderSend error ", GetLastError(), " retcode: ", result.retcode); return false; } return true; }需要特别关注的是“偏差”参数——它决定了订单可在请求价格之外多少范围内成交:
input int Deviation = 3; // Acceptable price deviation
这相当于您与市场魔鬼达成的协议:“我愿意接受比我请求价格差3个点的成交价,但不能再多了。”在市场剧烈波动时期,这可能决定订单是成交还是错失良机。如果偏差值设置过小,订单会因报价变动而被拒绝;反之设置过大,则可能以意外糟糕的价格成交。
实时信息展示与分析:交易者的耳目
在开发TrisWeb_Optimized之初,我就意识到许多EA的一个关键问题在于它们像“黑箱”一样运作,让交易者无法理解其内部逻辑。因此,我通过DisplayInfo()函数添加了详细信息的输出功能:
void DisplayInfo(int totalOrders, double totalProfit, double profit1, double profit2, double profit3, int count1, int count2, int count3) { string info = ""; if(AutoLotOptimization) { double lot1 = CalculateOptimalLotSize(Symbol1, Lot_Symbol1); double lot2 = CalculateOptimalLotSize(Symbol2, Lot_Symbol2); double lot3 = CalculateOptimalLotSize(Symbol3, Lot_Symbol3); info += "Auto Lot: " + Symbol1 + "=" + DoubleToString(lot1, 2) + ", " + Symbol2 + "=" + DoubleToString(lot2, 2) + ", " + Symbol3 + "=" + DoubleToString(lot3, 2) + "\n"; } // ... the rest of the information generation code Comment(info); }您可以选择基本显示模式(适合极简主义者),也可以选择包含各货币对详细分析的标准模式:
input bool DisplayDetailedInfo = false; // Show detailed information
这就像老式汽车的基本仪表盘(只有速度表和油量表)与现代驾驶舱(有几十个仪表和显示屏)的区别——选择取决于您的驾驶风格。
以下是旧版本系统其中一套策略的表现:
系统扩展:从简单机器人到交易帝国
TrisWeb_Optimized不仅是一个现成的EA,更是构建您自己的套利帝国的基石。在其五年的发展历程中,我不断地对其进行修改,添加新功能并优化现有功能。以下是您可以进一步开发系统的几个方向:
与Python集成,为相关性分析和机器学习方法的应用开辟了巨大可能性。想象一下,您不仅能分析当前报价,还能解析三个货币对之间历史互动模式,预测最有可能出现的失衡情况。
通过Telegram API发送通知,为您的交易策略增添了灵活性——即使您不在交易终端前,也能随时了解重要事件。当EA在远程虚拟专用服务器(VPS)上运行时,这一点尤其有用。
扩展到更多货币对,使TrisWeb成为一个成熟的套利平台。既然您可以创建一个由数十个相互关联的货币对组成的网络,追踪数百个潜在的套利机会,为何还要局限于三个交易工具呢?
所有这些修改只需对现有代码进行最小程度的更改,同时保持其基本结构和运行逻辑。这就像在现有房屋上扩建房间——地基已经打好,只需扩大居住空间即可。
结语
五年前,当TrisWeb_Optimized的第一个版本发布时,我从未想过后续会走上这样的道路。它经历了市场风暴、极端波动和相对平静的时期。它已经从一个简单的脚本发展成为一个成熟的交易系统。但最重要的是,它从未停止过盈利。
在本文的下一部分,我们将深入探讨TrisWeb_Optimized的实战设置,考察系统运行的实际案例,并分享针对各种市场条件优化参数的秘诀。敬请期待——最精彩的部分还在后面!
本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/17424
注意: MetaQuotes Ltd.将保留所有关于这些材料的权利。全部或部分复制或者转载这些材料将被禁止。
本文由网站的一位用户撰写,反映了他们的个人观点。MetaQuotes Ltd 不对所提供信息的准确性负责,也不对因使用所述解决方案、策略或建议而产生的任何后果负责。
从新手到专家:使用 MQL5 制作动画新闻标题(四) — 本地托管 AI 模型市场洞察
神经类群优化算法 (NOA)
新手在交易中的10个基本错误
从新手到专家:使用 MQL5 制作动画新闻标题 (三) — 指标洞察
在文章中发表或在 CodeBase 中发布的智能交易系统无法盈利。
盈利与否是交易者和技术手段(包括智能交易系统)共同作用的结果。
文章和代码库中有很多合理的建议,但越往后,错误的建议就越多,这对交易者和开发者都没有任何帮助。
盈利与否是交易者和技术手段(包括顾问)共同作用的结果。
在文章和代码库中有很多合理的建议,但越往后,错误的建议就越多,这对交易者和开发者都没有任何帮助。 货币合成套利就是其中之一。
...我把它编入了 EA...
你好,非常有趣,你在 EA 中编了什么程序?我想知道详情。
敬上,弗拉基米尔
我不得不说,这家伙是乎一无所知
这个值永远是 0, 从这里就可以看出,他是来骗稿费的 😂😂😂😂
关键词是 "曾经是"!)但现在不是了。