
价格行为分析工具包开发系列(第4部分):分析预测型EA
内容:
概述
在从脚本转型为EA后,先前的工具——分析大师EA(Analytics Master EA)——旨在分析关键指标,并直接在图表上提供持续更新。尽管它作为一项基础工具发挥了重要作用,但其功能仅限于在图表内部获取分析信息。在继续开发更高级的分析工具之前,我认为加强分析信息的传播方式至关重要。
在本文中,我们重点将传播方式与Telegram集成,以确保分析信息能够更广泛地传播。我选择Telegram作为集成平台,是因为它在交易者中广受欢迎且界面易于使用。将MetaTrader 5的图表更新与Telegram集成,可为活跃交易者带来显著优势。这种设置能够即时提供关键市场信息,提升用户体验,并改善沟通效果。因此,您可以制定更有效的策略,并在快速变化的市场中迅速做出反应。通过这种集成,您可以增加成功的机会,并做出更明智、更及时的决策。
上一篇文章回顾
让我们回顾一下我们先前的工具——分析大师EA。我们正将该工具中的相同分析信息集成到Telegram中。如需了解更多信息,请访问链接https://www.mql5.com/en/articles/16434。分析大师EA旨在分析和计算以下关键市场指标:
- 前一日的开盘价和收盘价
- 前一日的成交量
- 当日的成交量
- 前一日的最高价和最低价
- 关键支撑位和阻力位
- 账户余额
- 账户净值
- 市场点差
- 最小和最大交易手数
- 市场波动性
理解这些指标值对交易者至关重要,因为它们能提供对市场行为和趋势的洞察。前一日的指标有助于为当前市场状况建立背景,而当前指标则有助于评估市场表现。通过识别支撑位和阻力位,交易者可以就入场和出场点做出更明智的决策。此外,了解账户余额和净值可确保有效管理交易风险。深入了解市场点差、交易手数和波动性对于优化交易执行、最大化潜在利润并最小化风险至关重要。总体而言,对这些指标的扎实掌握使交易者能够制定明智的策略并提高整体交易表现。
该EA会为关键支撑位和阻力位绘制趋势线,并根据计算出的指标提供预期的市场方向。所有这些信息都以表格形式呈现在图表上,并每两小时定期更新一次。请参见下面的图例1。
图例1. 结果分析
分析部分还包含了最后更新时间,以便用户能轻松查阅最新信息。该工具仅专为市场分析而设计,不会自动执行交易。用户必须根据分析得出的信息和生成的信号手动执行交易。为了获得最优效果,将此数据与用户自身的交易策略相结合至关重要。
项目概述
MetaTrader 5与Telegram的集成,涉及将MetaTrader 5交易平台与Telegram这一即时通讯服务相连,使交易者能够在Telegram聊天中直接接收有关其交易活动的即时通知、警报和分析。这种集成利用了Telegram Bot API,实现了从在MetaTrader 5上运行的交易算法或EA到指定Telegram聊天的自动化通信。下图总结了所有内容。
图例2. 集成路径
集成的关键组件
- Telegram机器人:在Telegram上使用BotFather创建一个Telegram机器人,该机器人会提供一个访问令牌,用于验证发送到Telegram API的请求。
- 聊天ID:确定应发送消息的聊天ID。这可以是个人聊天或群组聊天,用于指定警报将要发送到的目标位置。
- MetaTrader 5:利用MQL5编程语言开发或修改能与Telegram API连接的EA或脚本。这通常涉及使用HTTP POST请求来发送消息。
搭建Telegram机器人并获取图表ID
Telegram机器人是在Telegram消息平台上运行的自动化软件应用,能够通过自动化任务与用户进行交互。其主要功能之一是通过无需人工干预的方式,快速且准确地响应用户查询,从而简化沟通流程。这一功能使企业和开发者能够自动化执行各种任务,如发送通知和处理命令,从而提升用户体验和参与度。
此外,Telegram机器人在信息检索方面也表现出色;它们可以从外部来源(如市场数据或新闻源)获取数据,并直接将其提供给用户。在交易领域,机器人对于根据预设条件向用户发出特定市场事件、价格变动或信号警报特别有价值。它们能够与API和其他服务集成,进一步增强了其执行数据分析、报告等高级功能的能力,使其成为各种应用的通用工具。按照以下步骤创建您的Telegram机器人:
步骤1:打开Telegram应用
确保您的设备上已安装Telegram应用。
步骤2:搜索BotFather
图例3. Botfather
在应用的搜索栏中输入BotFather。
BotFather是一个官方Telegram机器人,允许您创建和管理其他机器人。
步骤3:与BotFather开始聊天
图例4. 步骤3和4
点击BotFather结果以开启聊天。
点击开始按钮,或输入 /start,以开启对话。
步骤4:创建新机器人
输入命令 /newbot并发送。
BotFather将提示您为机器人选择一个名称。这是用户将看到的显示名称。
输入名称后,系统将要求您为机器人提供一个用户名。用户名必须以“bot”结尾(例如,MyCoolBot)。
步骤5:接收您的机器人令牌
图例5. 步骤5
完成上述步骤后,BotFather将创建您的机器人,并为您提供一个唯一的API令牌。此令牌对于与Telegram Bot API交互至关重要,因此请将其安全保管。
创建Telegram机器人后,下一步是找到您的聊天ID。另一方面,图表ID是分配给交易应用或图表工具中特定数据可视化或图表的唯一标识符。这些ID在图表的识别和检索中起着至关重要的作用,使用户和开发者能够轻松引用特定的可视化内容。图表ID有助于提取与特定图表相关的当前或历史数据,从而实现对数据的定制化分析。这一方面在交易中尤其有益,因为它使用户能够快速访问相关信息,从而做出明智的决策。
此外,图表ID支持定制化,允许开发者根据个人用户偏好或交易策略修改参数和设置。当与Telegram机器人集成时,图表ID可以显著增强功能;它们使机器人能够在聊天界面中直接为用户提供特定的数据可视化内容,从而简化获取信息和做出交易决策的过程。以下是使用Telegram机器人获取聊天ID的两种方法。
方法1:使用获取ID机器人
这是一种直接的方法。您可以搜索并打开如@get_id_bot或@userinfobot等机器人。一旦您通过点击开始按钮或输入 /start启动机器人,它将回复您的聊天ID,您可以将其记录下来。
图例6. 获取ID
方法2:使用网页浏览器
首先,在Telegram中向您的机器人发送任何消息。然后,打开网页浏览器并输入以下URL,将替换为您的实际机器人令牌:
https://api.telegram.org/bot<YourBotToken>/getUpdates
输入后,检查API返回的响应。您的聊天ID将在响应的“结果”部分。
在EA中实现Telegram集成
将Telegram集成到EA中,涉及将Telegram的消息功能融入我们在MetaTrader的EA中。这种集成使EA能够直接向Telegram账户发送即时通知和警报,使用户能够随时了解市场状况、关键指标和其他重要交易信息。通过利用Telegram的API,可以增强EA的功能,确保用户无需不断检查交易平台即可接收重要更新。这提高了对市场变化的响应速度,最终使交易体验更加高效。
通过融入能够将分析后的指标转发到Telegram应用的命令,对分析大师EA的代码进行了改进。我将提供完整的集成MQL5代码,并逐步指导您完成集成过程。
分析预测器(EA)代码
//+-------------------------------------------------------------------+ //| Analytics Forecaster EA.mq5| //| Copyright 2024, Christian Benjamin| //| https://www.mql5.com| //+-------------------------------------------------------------------+ #property copyright "2024, MetaQuotes Software Corp." #property link "https://www.mql5.com/en/users/lynnchris" #property description "EA for market analysis,commenting and Telegram Integeration" #property version "1.1" #property strict // Inputs for risk management input double RiskPercentage = 1.0; // Percentage of account balance to risk per trade input double StopLossMultiplier = 1.0; // Multiplier for determining the stop loss distance input int ATR_Period = 14; // Period for ATR calculation // Telegram configuration input string TelegramToken = "YOUR BOT TOKEN"; // Your Telegram bot token input string ChatID = "YOUR CHART ID"; // Your chat ID input bool SendTelegramAlerts = true; // Option to enable/disable Telegram notifications // Global variables for storing values datetime lastUpdateTime = 0; double previousDayOpen, previousDayClose, previousDayHigh, previousDayLow; double previousDayVolume; double currentDayVolume; double support, resistance; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { lastUpdateTime = 0; // Set the initial update time return INIT_SUCCEEDED; } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { ObjectsDeleteAll(0); // Clean up any drawn objects on the current chart } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { UpdateMetrics(); // Call to the function that fetches and displays the metrics } //+------------------------------------------------------------------+ //| Update metrics and display them | //+------------------------------------------------------------------+ void UpdateMetrics() { // Check if 2 hours have passed since the last update if(TimeCurrent() - lastUpdateTime >= 2 * 3600) { // Fetch previous day's data datetime prevDay = iTime(NULL, PERIOD_D1, 1); previousDayOpen = iOpen(NULL, PERIOD_D1, 1); previousDayClose = iClose(NULL, PERIOD_D1, 1); previousDayHigh = iHigh(NULL, PERIOD_D1, 1); previousDayLow = iLow(NULL, PERIOD_D1, 1); previousDayVolume = iVolume(NULL, PERIOD_D1, 1); // Fetch current day's volume currentDayVolume = iVolume(NULL, PERIOD_D1, 0); // Volume for today // Calculate support and resistance support = previousDayLow - (previousDayHigh - previousDayLow) * 0.382; // Fibonacci level resistance = previousDayHigh + (previousDayHigh - previousDayLow) * 0.382; // Fibonacci level // Determine market direction string marketDirection = AnalyzeMarketDirection(previousDayOpen, previousDayClose, previousDayHigh, previousDayLow); // Calculate possible lot size based on risk management double lotSize = CalculateLotSize(support, resistance); // Retrieve account metrics double accountBalance = AccountInfoDouble(ACCOUNT_BALANCE); double accountEquity = AccountInfoDouble(ACCOUNT_EQUITY); // Calculate market spread manually double marketBid = SymbolInfoDouble(_Symbol, SYMBOL_BID); double marketAsk = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double marketSpread = marketAsk - marketBid; // Calculate spread double minLotSize = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN); double maxLotSize = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX); // Calculate market volatility using ATR int atrHandle = iATR(NULL, PERIOD_H1, ATR_Period); // Get the ATR handle double atrValue = 0.0; if(atrHandle != INVALID_HANDLE) // Check if the handle is valid { double atrBuffer[]; // Array to hold the ATR values if(CopyBuffer(atrHandle, 0, 0, 1, atrBuffer) > 0) // Copy the latest ATR value { atrValue = atrBuffer[0]; // Retrieve the ATR value from the buffer } IndicatorRelease(atrHandle); // Release the indicator handle } // Create the output string, including pair name and last update time string pairName = Symbol(); // Get the current symbol name string lastUpdateStr = TimeToString(TimeCurrent(), TIME_DATE | TIME_MINUTES); string infoStr = StringFormat("Pair: %s\nPrev Day Open: %.2f\nPrev Day Close: %.2f\nPrev Day High: %.2f\nPrev Day Low: %.2f\n" "Prev Day Volume: %.0f\nCurrent Day Volume: %.0f\nMarket Direction: %s\n" "Support: %.2f\nResistance: %.2f\nAccount Balance: %.2f\nAccount Equity: %.2f\n" "Market Spread: %.2f\nMin Lot Size: %.2f, Max Lot Size: %.2f\n" "Market Volatility (ATR): %.2f\nLast Update Time: %s\nPossible Lot Size: %.2f", pairName, previousDayOpen, previousDayClose, previousDayHigh, previousDayLow, previousDayVolume, currentDayVolume, marketDirection, support, resistance, accountBalance, accountEquity, marketSpread, minLotSize, maxLotSize, atrValue, lastUpdateStr, lotSize); // Log the information Print(infoStr); // Display information on the chart Comment(infoStr); // Send Telegram notification if(SendTelegramAlerts) SendTelegramMessage(infoStr); // Remove old trend lines and create new ones for previous day's high/low ObjectsDeleteAll(0); // Draw continuous trend lines DrawContinuousTrendLine("PrevDayHigh", previousDayHigh); DrawContinuousTrendLine("PrevDayLow", previousDayLow); // Update last update time lastUpdateTime = TimeCurrent(); } } //+------------------------------------------------------------------+ //| Analyze market direction | //+------------------------------------------------------------------+ string AnalyzeMarketDirection(double open, double close, double high, double low) { string direction; if(close > open) { direction = "Bullish"; } else if(close < open) { direction = "Bearish"; } else { direction = "Neutral"; } // Include current trends or patterns based on high and low for further analysis if(high > open && high > close) { direction += " with bullish pressure"; // Example addition for context } else if(low < open && low < close) { direction += " with bearish pressure"; // Example addition for context } return direction; } //+------------------------------------------------------------------+ //| Draw a continuous trend line to the left on the chart | //+------------------------------------------------------------------+ void DrawContinuousTrendLine(string name, double price) { datetime startTime = TimeCurrent() - 720 * 3600; // Extend 24 hours into the past ObjectCreate(0, name, OBJ_TREND, 0, startTime, price, TimeCurrent(), price); ObjectSetInteger(0, name, OBJPROP_COLOR, (StringFind(name, "High") >= 0) ? clrRed : clrBlue); ObjectSetInteger(0, name, OBJPROP_WIDTH, 2); // Set thickness of the line ObjectSetInteger(0, name, OBJPROP_XSIZE, 0); // Set this property to extend the line infinitely to the left } //+------------------------------------------------------------------+ //| Calculate the lot size based on risk management | //+------------------------------------------------------------------+ double CalculateLotSize(double support, double resistance) { double stopLossDistance = MathAbs((support - resistance) * StopLossMultiplier); double riskAmount = AccountInfoDouble(ACCOUNT_BALANCE) * (RiskPercentage / 100.0); // Get the tick size for the current symbol double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE); // Calculate the lot size based on the stop loss and tick size double lotSize = riskAmount / (stopLossDistance / tickSize); // Adjusted for the correct pip size lotSize = NormalizeDouble(lotSize, 2); // Normalize the lot size to two decimal places // Ensure lot size is above minimum lot size allowed by broker double minLotSize = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN); if(lotSize < minLotSize) lotSize = minLotSize; return lotSize; } //+------------------------------------------------------------------+ //| Send message to Telegram API | //+------------------------------------------------------------------+ void SendTelegramMessage(string message) { string url = StringFormat("https://api.telegram.org/bot%s/sendMessage", TelegramToken); string headers = "Content-Type: application/json\r\n"; // Content type for JSON int timeout = 1000; // Timeout in milliseconds // Format the data as JSON string postData = StringFormat("{\"chat_id\":\"%s\",\"text\":\"%s\"}", ChatID, message); // Convert the string to a char array char dataArray[]; StringToCharArray(postData, dataArray); // Prepare the result buffer and response headers char result[]; string responseHeaders; // Perform the web request int responseCode = WebRequest("POST", url, headers, timeout, dataArray, result, responseHeaders); if(responseCode == 200) // HTTP 200 OK { Print("Message sent successfully!"); } else { PrintFormat("Error sending message. HTTP Response Code: %d. Error: %s", responseCode, GetLastError()); } } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+
1. 声明输入变量:
在编写我们的EA时,一开始我们就应该声明必要的输入变量。在MQL5中,输入变量能让交易者无需深入代码内部,即可对EA的运行方式进行自定义设置。这使得交易策略能够更轻松且快速地调整适应。给变量命名时,采用直观的名称至关重要。例如,TelegramToken这个名称就清晰地表明了它的用途。考虑为变量设置符合常见做法或与您的交易策略设置相契合的默认值,这样在测试时就能减少配置的复杂程度。
input string TelegramToken = "YOUR_BOT_API_TOKEN"; // Replace with your actual bot token input string ChatID = "YOUR_CHAT_ID"; // Replace with your actual chat ID input bool SendTelegramAlerts = true; // Control whether alerts are sent
请记得将“YOUR_BOT_API_TOKEN”和“YOUR_CHAT_ID”替换为实际值。
2. 创建消息发送函数:
SendTelegramMessage函数能够有效地构建一个结构化的HTTP POST请求,发送至Telegram API,从而向指定的聊天群组发送通知。该函数通过准备API网址、设置请求头、将消息数据格式化为JSON、执行请求并处理响应,使EA能够通过Telegram即时向用户传达更新信息。这种精简的逻辑设计使得交易和警报信息能够迅速传达,并通过轻松保持用户知情的方式,增强了EA作为交易助手的整体功能。
- 函数用途:此函数负责与Telegram API进行通信。它封装了向我们的Telegram机器人发送消息所需的逻辑。通过创建可重用的函数,我们确保了代码的清晰性并减少了重复。
- 错误处理:融入错误处理机制至关重要。无论何时发送消息,我们都要不仅记录成功发送的信息,还要记录出现的任何错误。这种做法有助于调试并提供反馈。
void SendTelegramMessage(string message) { string url = StringFormat("https://api.telegram.org/bot%s/sendMessage", TelegramToken); string headers = "Content-Type: application/json\r\n"; int timeout = 1000; string postData = StringFormat("{\"chat_id\":\"%s\",\"text\":\"%s\"}", ChatID, message); char dataArray[]; StringToCharArray(postData, dataArray); char result[]; string responseHeaders; int responseCode = WebRequest("POST", url, headers, timeout, dataArray, result, responseHeaders); if (responseCode == 200) { Print("Message sent successfully! Response: ", CharArrayToString(result)); } else { PrintFormat("Error sending message. HTTP Response Code: %d. Error: %s", responseCode, GetLastError()); } }
- 理解WebRequest:WebRequest函数至关重要,因为它允许我们的EA向API发起HTTP请求。为确保功能正常,请在EA属性中启用“允许自动交易”选项。
3. 触发Telegram消息
- 时间检查与数据获取
代码的第一部分启动时间检查,以确定自上次更新市场指标以来是否已过去两小时。通过使用TimeCurrent()函数,代码获取当前时间,并将其与lastUpdateTime变量进行比较。如果已经过去两小时以上,EA将继续收集与市场状况相关的最新数据。此检查对于防止EA过于频繁地向Telegram聊天群组发送消息至关重要,因为过于频繁的消息可能会被用户视为垃圾信息。
// Check if 2 hours have passed since the last update if (TimeCurrent() - lastUpdateTime >= 2 * 3600) { // ... [Code that fetches data and calculates support/resistance, etc.] }
- 创建输出字符串
在第二部分中,会生成一个详细的输出字符串(称为infoStr),用于整合从EA操作中收集到的市场指标数据。代码会获取当前交易品种的名称对,此外,还会使用lastUpdateStr为消息格式化当前时间。然后,使用StringFormat函数构建消息,其中包含各种占位符,这些占位符将被特定的指标数据所替换,例如前一日的最高价、最低价、开盘价和收盘价、当日成交量、市场走势以及其他账户详情。这个格式化后的字符串是整个操作的关键部分,因为它以清晰、有条理的方式总结了当前的市场状况,随后将通过Telegram发送出去。
// Create the output string, including pair name and last update time string pairName = Symbol(); // Get the current symbol name string lastUpdateStr = TimeToString(TimeCurrent(), TIME_DATE | TIME_MINUTES); string infoStr = StringFormat("Pair: %s\nPrev Day Open: %.2f\nPrev Day Close: %.2f\n" "Prev Day High: %.2f\nPrev Day Low: %.2f\n" "Prev Day Volume: %.0f\nCurrent Day Volume: %.0f\n" "Market Direction: %s\nSupport: %.2f\nResistance: %.2f\n" "Account Balance: %.2f\nAccount Equity: %.2f\n" "Market Spread: %.2f\nMin Lot Size: %.2f, Max Lot Size: %.2f\n" "Market Volatility (ATR): %.2f\nLast Update Time: %s\nPossible Lot Size: %.2f", pairName, previousDayOpen, previousDayClose, previousDayHigh, previousDayLow, previousDayVolume, currentDayVolume, marketDirection, support, resistance, accountBalance, accountEquity, marketSpread, minLotSize, maxLotSize, atrValue, lastUpdateStr, lotSize);
- 信息记录与展示
第三部分主要围绕构建好的信息的记录与展示。调用Print (infoStr)函数可将消息记录到MetaTrader平台的“Experts”选项卡中,这样就能查看通过Telegram发送的信息内容。这样就提供了一个实用的调试工具,可用于确认各项指标是否正确生成。此外,使用Comment(infoStr)命令可在交易图表上直接显示相同的信息,让交易者无需查看日志就能直观地确认各项指标。这些步骤能让用户了解所报告的指标情况,并在将数据发送至Telegram之前验证其准确性。
// Log the information Print(infoStr); // Here the information is logged for debugging // Display information on the chart Comment(infoStr); // Display the same information on the chart
- 发送Telegram通知
在最后一部分,代码负责实际发送Telegram通知。(SendTelegramAlerts)语句会检查发送警报的选项是否已启用,这样用户无需修改代码就能轻松禁用通知。如果警报功能已启用,则会调用SendTelegramMessage(infoStr)函数,将精心构建的消息发送到指定的Telegram聊天群组。这一步至关重要,因为它是将市场指标有效传达给用户的关键环节。随后,代码通过设置lastUpdateTime = TimeCurrent(),将lastUpdateTime变量更新为当前时间,从而意味着本次更新周期的结束,并确保下一次更新的时间间隔符合之前设定的两小时。
// Send Telegram notification if (SendTelegramAlerts) // Check if sending alerts is enabled SendTelegramMessage(infoStr); // Send the constructed message // Update last update time lastUpdateTime = TimeCurrent();
- 当前交易品种名称
我还添加了一项功能,即在显示分析得出的各项指标数据时,同时展示当前交易品种名称,这样能更方便地识别正在分析的是哪个交易品种。
// Create the output string, including pair name and last update time string pairName = Symbol(); // Get the current symbol name
以下是信息在Telegram上的显示样式:
图例7. 交易品种结果
测试
在测试之前,需要对您的MetaTrader 5进行一些调整,以确保信息能够顺利地传送到Telegram。
允许Web请求:
- 打开MetaTrader 5,然后依次点击“工具”>“选项”>“EA”。
图例8. 设置Web请求
- 勾选“允许对已列出的URL进行WebRequest”的复选框,并且将https://api.telegram.org添加到列表中。此设置允许EA向Telegram的API发送请求。
图例9. 设置Web请求
出于测试目的,您也可以将更新频率调低。在此情况下,我会将其从每2小时一次调整为每15秒一次。
//+------------------------------------------------------------------+ //| Update metrics and display them | //+------------------------------------------------------------------+ void UpdateMetrics() { // Check if 15 seconds have passed since the last update if(TimeCurrent() - lastUpdateTime >= 15)
现在,请在MetaEditor中编译您的MQL5代码,并将EA或脚本附加到MetaTrader 5的图表上。成功编译后,请将您的EA拖放到图表上。之后,您应该会开始在Telegram上收到来自该EA发送的更新通知。以下是Telegram上的测试结果展示。
图例10. Telegram测试结果
下图还表明,MetaTrader 5图表上提供的信息与Telegram中的相关信息一致。
图例11. 测试结果
结论
总而言之,如上文图表所示,分析预测型EA的成功在于其采用先进的市场分析方法,并通过与Telegram集成实现及时通知。该EA通过运用多种交易指标,如前一日数据、当前成交量对比、市场走势以及风险管理原则,为交易者提供有价值的见解。计算得出的支撑位和阻力位,加上自动确定的交易手数,使交易者能够做出更明智的交易决策,确保新手和经验丰富的交易者都能根据市场状况调整策略,同时有效管理风险。
此外,与Telegram的无缝集成通过及时推送更新增强了用户交互体验,使交易者能够迅速应对市场变化。能够在移动平台上接收关键交易信息,极大地提高了交易监控的便利性,同时也营造了一个反应更迅速的交易环境。总体而言,分析预测型EA在自动化分析和风险管理方面展现出卓越能力,使交易者能够在动态市场中优化自身表现。该EA注重数据准确性且具备用户友好特性,堪称交易者工具库中的强大工具,为自动化交易解决方案的未来发展铺平了道路。
日期 | 工具名 | 描述 | 版本 | 更新 | 备注 |
---|---|---|---|---|---|
01/10/24 | 图表展示器 | 以重影效果覆盖前一日价格走势的脚本 | 1.0 | 初始版本 | Lynnchris工具箱的第一个工具 |
18/11/24 | 分析评论 | 以表格形式提供前一日的信息,并预测市场的未来方向 | 1.0 | 初始版本 | Lynnchris工具箱的第二个工具 |
27/11/24 | 分析大师 | 每两小时定期更新市场指标 | 1.01 | 第二个版本 | Lynnchris工具箱的第三个工具 |
02/12/2024 | 分析预测 | 集成Telegram通知功能,每两小时定时更新市场指标 | 1.1 | 第三个版本 | 工具数5 |
本文由MetaQuotes Ltd译自英文
原文地址: https://www.mql5.com/en/articles/16559
注意: MetaQuotes Ltd.将保留所有关于这些材料的权利。全部或部分复制或者转载这些材料将被禁止。
This article was written by a user of the site and reflects their personal views. MetaQuotes Ltd is not responsible for the accuracy of the information presented, nor for any consequences resulting from the use of the solutions, strategies or recommendations described.



