作者:老余捞鱼
原创不易,转载请标明出处及原作者。

写在前面的话:大家好,我发现将机器学习与SMA、EMA结合,可以自动优化止盈点,显著提升交易收益。以苹果股票为例,这种策略让我的收益提升了50%!如果你也想告别手动操作,打造智能交易系统,本文将为你详细解析如何用SMA和EMA打造高效的自动止盈策略的智能投顾系统。
一、概述
接下来将带您一起开发一款智能交易系统,其融合机器学习技术与传统技术分析方法。该系统专为苹果这类科技股的交易量身定制,集成了多项核心功能:

- 自适应优化:算法根据市场情况不断调整参数。
- 全面风险管理:实施精密的风险控制措施,以防出现重大损失。
- 多策略方法:综合运用各种交易策略,充分利用各种市场情况。
- 机器学习集成:采用 ML 算法来增强预测能力和决策能力。
而回测结果证明了该系统的潜力:

- 盈利能力强:在测试期间有可观的回报。
- 显著缩水:表示出现大幅亏损的时期,表明还有改进的余地。
尽管智能投顾系统展现了巨大的潜力,但市场波动带来的大幅回撤表明,系统仍需进一步优化和完善。这也揭示了算法交易中存在的内在风险,强调了持续开发迭代和强化风险管理的至关重要性。
二、功能实现
主要功能包括:
- 使用机器学习(ONNX 模型)进行价格预测。
- 结合技术指标(SMA、EMA)和 ML 预测,做出交易决策。
- 执行多种追踪止损策略。
- 包括定期优化指标参数和交易设置。
- 具有内置的风险管理(批量大小、资金检查)。
- 考虑兼容不同市场交易时间。

该智能交易系统(EA)相当复杂,将传统的技术分析与机器学习相结合。它还包括各种风险管理和优化功能,以适应不断变化的市场条件。
2.1 初始设置
代码以版权信息开始,包括 Trade.mqh 等必要的库。
#include <Trade\Trade.mqh>
2.2 全局变量和参数
- 定义 ONNX 模型参数,包括样本量和手柄。
- 声明了指标(SMA、EMA、ATR)和交易操作的输入参数。
- 为价格变动和神奇数字定义了枚举和常量。
#resource "/Files/model.EURUSD.D1.1_1_2024.onnx" as uchar ExtModel[];
input group "----- Indicators Parameters -----"
int SMA_Period = 20;
int EMA_Period = 50;
input double StopLossATR = 1.5;
input double TakeProfitATR = 3.0;
input int OptimizationDays = 1; // Hours between optimizations
input int LookbackPeriod = 7; // Hours loockback periods
input int MinSMAPeriod = 5; // Period min para SMA
input int MaxSMAPeriod = 50; // Periodo max para SMA
input int MinEMAPeriod = 5; // Periodo min para EMA
input int MaxEMAPeriod = 50; // Periodo max para EMA
#define MAGIC_SE 12321
datetime lastOptimizationTime = 0;
double optimizedTakeProfit = 0.0;//InpTakeProfit;
double optimizedStopLoss = 0.0;//InpStopLoss;
double InpTakeProfit1 ;
double InpStopLoss1;
2.3 初始化函数(OnInit)
- 从缓冲区设置 ONNX 模型。
- 初始化技术指标(SMA、EMA)。
- 调用优化指标和交易参数的功能。
int OnInit()
{
//--- create a model from static buffer
ExtHandle = OnnxCreateFromBuffer(ExtModel, ONNX_DEFAULT);
if(ExtHandle == INVALID_HANDLE)
{
Print("OnnxCreateFromBuffer error ", GetLastError());
return(INIT_FAILED);
}
//--- set input and output shapes
const long input_shape[] = {1, SAMPLE_SIZE, 1};
if(!OnnxSetInputShape(ExtHandle, ONNX_DEFAULT, input_shape))
{
Print("OnnxSetInputShape error ", GetLastError());
return(INIT_FAILED);
}
const long output_shape[] = {1, 1};
if(!OnnxSetOutputShape(ExtHandle, 0, output_shape))
{
Print("OnnxSetOutputShape error ", GetLastError());
return(INIT_FAILED);
}
SMAHandle = iMA(_Symbol, _Period, SMA_Period, 0, MODE_SMA, PRICE_CLOSE); // Ensure correct period
if(SMAHandle == INVALID_HANDLE)
{
Print("Error initializing SMA indicator: ", GetLastError());
return INIT_FAILED;
}
EMAHandle = iMA(_Symbol, _Period, EMA_Period, 0, MODE_EMA, PRICE_CLOSE); // Ensure correct index
if(EMAHandle == INVALID_HANDLE)
{
Print("Error initializing EMA indicator: ", GetLastError());
return INIT_FAILED;
}
trade.SetDeviationInPoints(Slippage);
trade.SetExpertMagicNumber(MAGIC_SE);
OptimizeIndicators();
OptimizeParameters();
return(INIT_SUCCEEDED);
}
2.4 注销功能(OnDeinit)
发布 ONNX 模型和指标的句柄。
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
if(ExtHandle != INVALID_HANDLE)
{
OnnxRelease(ExtHandle);
ExtHandle = INVALID_HANDLE;
}
IndicatorRelease(SMAHandle);
IndicatorRelease(EMAHandle);
}
2.5 主要交易逻辑(OnTick)
- 检查市场是否关闭。
- 定期优化指标和交易参数。
- 更新追踪止损逻辑。
- 使用 ONNX 模型预测价格走势。
- 根据预测和指标检查打开/关闭位置条件。
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
if(IsMarketClosed()) // Verificar si el mercado está cerrado
{
return; // Si el mercado está cerrado, no hacer nada
}
static datetime lastOptimizationTime2 = 0;
if(TimeCurrent() - lastOptimizationTime2 >= OptimizationDays * PeriodSeconds(PERIOD_H1))
{
OptimizeIndicators();
lastOptimizationTime2 = TimeCurrent();
// Actualizar los indicadores con los nuevos períodos
IndicatorRelease(SMAHandle);
IndicatorRelease(EMAHandle);
SMAHandle = iMA(_Symbol, _Period, SMA_Period, 0, MODE_SMA, PRICE_CLOSE);
EMAHandle = iMA(_Symbol, _Period, EMA_Period, 0, MODE_EMA, PRICE_CLOSE);
}
//--- Optimización cada 2 días
if(TimeCurrent() - lastOptimizationTime >= PeriodSeconds(PERIOD_H1) * HoursAnalyze)
{
OptimizeParameters();
lastOptimizationTime = TimeCurrent();
}
//---
if(NewBarTS()==true)//gather statistics and launch trailing stop
{
double open=iOpen(_Symbol,TFTS,1);
CalcLvl(up,(int)MathRound((iHigh(_Symbol,TFTS,1)-open)/_Point));
CalcLvl(dn,(int)MathRound((open-iLow(_Symbol,TFTS,1))/_Point));
buy_sl=CalcSL(dn);
buy_tp=CalcTP(up);
sell_sl=CalcSL(up);
sell_tp=CalcTP(dn);
if(TypeTS==Simple)//simple trailing stop
SimpleTS();
if(TypeTS==MoralExp)//Moral expectation
METS();
if(TypeTS==None)//None TS
return;
}
double bid=SymbolInfoDouble(_Symbol,SYMBOL_BID);
if(bid==SLNeutral || bid<=SLBuy || (SLSell>0 && bid>=SLSell))
{
for(int i=PositionsTotal()-1; i>=0; i--)
{
ulong ticket=PositionGetTicket(i);
if(PositionSelectByTicket(ticket)==true)
trade.PositionClose(ticket);
}
}
//---
//--- check new day
if(TimeCurrent() >= ExtNextDay)
{
GetMinMax();
ExtNextDay = TimeCurrent();
ExtNextDay -= ExtNextDay % PeriodSeconds(PERIOD_D1);
ExtNextDay += PeriodSeconds(PERIOD_D1);
}
//--- check new bar
if(TimeCurrent() < ExtNextBar)
return;
ExtNextBar = TimeCurrent();
ExtNextBar -= ExtNextBar % PeriodSeconds();
ExtNextBar += PeriodSeconds();
//--- check min and max
float close = (float)iClose(_Symbol, _Period, 0);
if(ExtMin > close)
ExtMin = close;
if(ExtMax < close)
ExtMax = close;
double sma[], ema[];//, willr[];
CopyBuffer(SMAHandle, 0, 0, 1, sma);
CopyBuffer(EMAHandle, 0, 0, 1, ema);
//CopyBuffer(WillRHandle, 0, 0, 1, willr);
//--- predict next price
PredictPrice();
//--- check trading according to prediction and indicators
if(ExtPredictedClass >= 0)
{
if(PositionSelect(_Symbol))
CheckForClose(sma[0], ema[0]);//, willr[0]);
else
CheckForOpen(sma[0], ema[0]);//, willr[0]);
}
}
2.6 交易功能
- CheckForOpen:根据预测和指标信号决定是否打开买入或卖出仓位。
- CheckForClose:检查是否应根据预测关闭当前仓位。
//+------------------------------------------------------------------+
//| Check for open position conditions |
//+------------------------------------------------------------------+
void CheckForOpen(double sma, double ema)//, double willr)
{
MqlRates rates[];
ArraySetAsSeries(rates,true);
int copied = CopyRates(_Symbol,0,0,1,rates);
if(copied <= 0)
{
Print("Error copying rates: ", GetLastError());
return;
}
double Close[1];
Close[0]=rates[0].close;
double close = Close[0];
ENUM_ORDER_TYPE signal = WRONG_VALUE;
Print("ExtPredictedClass ",ExtPredictedClass);
//--- check signals
if(ExtPredictedClass == 2)//PRICE_DOWN)
{
Print("ExtPredictedClass Sell ",ExtPredictedClass);
Print("close ",close, " sma ",sma, " ema ", ema);//, " willr ", willr);
// Venta
if((close < sma && close < ema))// || willr > -20)
{
signal = ORDER_TYPE_SELL;
Print("Order Sell detected");
}
}
else
if(ExtPredictedClass == 0)//PRICE_UP)
{
Print("ExtPredictedClass Buy ",ExtPredictedClass);
Print("close ",close, " sma ",sma, " ema ", ema);//, " willr ", willr);
// Compra
if((close > sma && close > ema))// || willr < -80)
{
signal = ORDER_TYPE_BUY;
Print("Order Buy detected");
}
}
//--- open position if possible according to signal
if(signal != WRONG_VALUE && TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
{
Print("Proceding open order");
double price, sl=0, tp=0;
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.deviation = Slippage;
request.magic = MAGIC_SE;
request.type_filling = ORDER_FILLING_FOK;
//request.comment = "AKWr";
double lotaje;
if(signal == ORDER_TYPE_SELL)
{
price = bid;
Print("Price: ",price);
if(inp_lot_type == LOT_TYPE_FIX)
lotaje=inp_lot_fix ;
else
lotaje=get_lot(price);
if(!CheckVolumeValue(lotaje))
return;
if(!InpUseStops && ATR)
{
sl = NormalizeDouble(bid + StopLossATR * ATRValue, _Digits);
tp = NormalizeDouble(ask - TakeProfitATR * ATRValue, _Digits);
if(!CheckMoneyForTrade(_Symbol, lotaje,ORDER_TYPE_SELL))
{
Print("No hay suficiente margen para abrir la posición");
return;
}
request.type = ORDER_TYPE_SELL;
request.price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
request.volume = lotaje;
request.sl = sl;
request.tp = tp;
request.comment = "SEW Opened sell order";
}
if(!InpUseStops && ATR)
{
sl = 0;
tp = 0;
}
else
{
InpTakeProfit1 =optimizedTakeProfit;
InpStopLoss1= optimizedStopLoss;
sl = NormalizeDouble(bid + InpStopLoss1*_Point, _Digits);
tp = NormalizeDouble(ask - InpTakeProfit1*_Point, _Digits);
}
}
else
{
price = ask;
Print("Price: ",price);
if(inp_lot_type == LOT_TYPE_FIX)
lotaje=inp_lot_fix ;
else
lotaje=get_lot(price);
if(!CheckVolumeValue(lotaje))
return;
if(!InpUseStops)
{
sl = NormalizeDouble(ask - StopLossATR * ATRValue, _Digits);
tp = NormalizeDouble(bid + TakeProfitATR * ATRValue, _Digits);
if(!CheckMoneyForTrade(_Symbol, lotaje,ORDER_TYPE_BUY))
{
Print("No hay suficiente margen para abrir la posición");
return;
}
request.type = ORDER_TYPE_BUY;
request.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
request.volume = lotaje;
request.sl = sl;
request.tp = tp;
request.comment = "SEW Opened buy order";
}
if(!InpUseStops && ATR)
{
sl = 0;
tp = 0;
}
else
{
InpTakeProfit1 =optimizedTakeProfit;
InpStopLoss1= optimizedStopLoss;
sl = NormalizeDouble(ask - InpStopLoss1*_Point, _Digits);
tp = NormalizeDouble(bid + InpTakeProfit1*_Point, _Digits);
}
}
Print("No InpUseStops used");
//ExtTrade.PositionOpen(_Symbol, signal, lotaje, price, sl, tp);
if(!CheckMoneyForTrade(_Symbol, lotaje, (ENUM_ORDER_TYPE)signal))
{
Print("No hay suficiente margen para abrir la posición");
return;
}
Print("Volume ", lotaje);
request.type = signal;
request.price = price;//SymbolInfoDouble(_Symbol, SYMBOL_ASK);
request.volume = lotaje;
request.sl = sl;
request.tp = tp;
request.comment = "SEW";
if(!OrderSend(request, result))
{
Print("Error opening the order: ", GetLastError());
return;
}
}
}
//+------------------------------------------------------------------+
//| Check for close position conditions |
//+------------------------------------------------------------------+
void CheckForClose(double sma, double ema)//, double willr)
{
if(InpUseStops)
return;
bool bsignal = false;
//--- position already selected before
long type = PositionGetInteger(POSITION_TYPE);
//--- check signals
if(type == POSITION_TYPE_BUY && ExtPredictedClass == 2)//PRICE_DOWN)
bsignal = true;
if(type == POSITION_TYPE_SELL && ExtPredictedClass == 0)//PRICE_UP)
bsignal = true;
//--- close position if possible
if(bsignal && TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
{
ExtTrade.PositionClose(_Symbol);
CheckForOpen(sma, ema);//, willr);
}
}
2.7 价格预测(PredictPrice)
使用 ONNX 模型预测未来价格走势。
//+------------------------------------------------------------------+
//| Predict next price |
//+------------------------------------------------------------------+
void PredictPrice(void)
{
static vectorf output_data(1);
static vectorf x_norm(SAMPLE_SIZE);
if(ExtMin >= ExtMax)
{
Print("ExtMin >= ExtMax");
ExtPredictedClass = -1;
return;
}
if(!x_norm.CopyRates(_Symbol, _Period, COPY_RATES_CLOSE, 1, SAMPLE_SIZE))
{
Print("CopyRates ", x_norm.Size());
ExtPredictedClass = -1;
return;
}
float last_close = x_norm[SAMPLE_SIZE - 1];
x_norm -= ExtMin;
x_norm /= (ExtMax - ExtMin);
if(!OnnxRun(ExtHandle, ONNX_NO_CONVERSION, x_norm, output_data))
{
Print("OnnxRun");
ExtPredictedClass = -1;
return;
}
float predicted = output_data[0] * (ExtMax - ExtMin) + ExtMin;
float delta = last_close - predicted;
if(fabs(delta) <= 0.00001)
ExtPredictedClass = PRICE_SAME;
else
if(delta < 0)
ExtPredictedClass = PRICE_UP;
else
ExtPredictedClass = PRICE_DOWN;
// Debugging output
Print("Predicted price: ", predicted, " Delta: ", delta, " Predicted Class: ", ExtPredictedClass);
}
2.8 追踪止损功能
各种功能(AllTS、METS、SimpleTS)实施不同的移动止损策略。
2.9 优化功能
- 优化参数:尝试不同的止盈和止损值,以找到最佳设置。
- 优化指标:查找 SMA 和 EMA 指标的最佳周期。
void OptimizeParameters()
{
double bestTakeProfit = InpTakeProfit1;
double bestStopLoss = InpStopLoss1;
double bestPerformance = -DBL_MAX;
for(int tp = 65; tp <= 500; tp += 5) // rango de TakeProfit
{
for(int sl = 65; sl <= 500; sl += 5) // rango de StopLoss
{
double performance = TestStrategy(tp, sl);
if(performance > bestPerformance)
{
bestPerformance = performance;
bestTakeProfit = tp;
bestStopLoss = sl;
//Print("Best Take Profit",bestTakeProfit);
//Print("Best Stop Loss",bestStopLoss);
}
}
}
optimizedTakeProfit = bestTakeProfit;
optimizedStopLoss = bestStopLoss;
Print("Optimized TakeProfit: ", optimizedTakeProfit);
Print("Optimized StopLoss: ", optimizedStopLoss);
}
void OptimizeIndicators()
{
datetime startTime = TimeCurrent() - LookbackPeriod * PeriodSeconds(PERIOD_H1);
datetime endTime = TimeCurrent();
int bestSMAPeriod = SMA_Period;
int bestEMAPeriod = EMA_Period;
double bestPerformance = -DBL_MAX;
for(int smaPeriod = MinSMAPeriod; smaPeriod <= MaxSMAPeriod; smaPeriod++)
{
for(int emaPeriod = MinEMAPeriod; emaPeriod <= MaxEMAPeriod; emaPeriod++)
{
double performance = TestIndicatorPerformance(smaPeriod, emaPeriod, startTime, endTime);
if(performance > bestPerformance)
{
bestPerformance = performance;
bestSMAPeriod = smaPeriod;
bestEMAPeriod = emaPeriod;
}
}
}
SMA_Period = bestSMAPeriod;
EMA_Period = bestEMAPeriod;
Print("Optimized SMA Period: ", SMA_Period);
Print("Optimized EMA Period: ", EMA_Period);
}
2.10 效用函数与资金管理
计算、交易量检查、市场关闭检查等功能,包括检查是否有足够资金进行交易以及将手数正常化等功能。
bool IsMarketClosed()
{
datetime currentTime = TimeCurrent();
MqlDateTime tm;
TimeToStruct(currentTime, tm);
int dayOfWeek = tm.day_of_week;
int hour = tm.hour;
// Verifica si es fin de semana
if(dayOfWeek <= Sunday || dayOfWeek >= Saturday)
{
return true;
}
// Verifica si está fuera del horario habitual de mercado (ejemplo: 21:00 a 21:59 UTC)
if(hour >= after || hour < before) // Ajusta estos valores según el horario del mercado
{
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| Check the correctness of the order volume |
//+------------------------------------------------------------------+
bool CheckVolumeValue(double volume)//,string &description)
{
//--- minimal allowed volume for trade operations
double min_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN);
if(volume<min_volume)
{
//description=StringFormat("Volume is less than the minimal allowed SYMBOL_VOLUME_MIN=%.2f",min_volume);
return(false);
}
//--- maximal allowed volume of trade operations
double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
if(volume>max_volume)
{
//description=StringFormat("Volume is greater than the maximal allowed SYMBOL_VOLUME_MAX=%.2f",max_volume);
return(false);
}
//--- get minimal step of volume changing
double volume_step=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP);
int ratio=(int)MathRound(volume/volume_step);
if(MathAbs(ratio*volume_step-volume)>0.0000001)
{
//description=StringFormat("Volume is not a multiple of the minimal step SYMBOL_VOLUME_STEP=%.2f, the closest correct volume is %.2f",
//volume_step,ratio*volume_step);
return(false);
}
//description="Correct volume value";
return(true);
}
//+------------------------------------------------------------------+
bool CheckMoneyForTrade(string symb,double lots,ENUM_ORDER_TYPE type)
{
//--- Getting the opening price
MqlTick mqltick;
SymbolInfoTick(symb,mqltick);
double price=mqltick.ask;
if(type==ORDER_TYPE_SELL)
price=mqltick.bid;
//--- values of the required and free margin
double margin,free_margin=AccountInfoDouble(ACCOUNT_MARGIN_FREE);
//--- call of the checking function
if(!OrderCalcMargin(type,symb,lots,price,margin))
{
//--- something went wrong, report and return false
Print("Error in ",__FUNCTION__," code=",GetLastError());
return(false);
}
//--- if there are insufficient funds to perform the operation
if(margin>free_margin)
{
//--- report the error and return false
Print("Not enough money for ",EnumToString(type)," ",lots," ",symb," Error code=",GetLastError());
return(false);
}
//--- checking successful
return(true);
}
double get_lot(double price)
{
if(inp_lot_type==LOT_TYPE_FIX)
return(normalize_lot(inp_lot_fix));
double one_lot_margin;
if(!OrderCalcMargin(ORDER_TYPE_BUY,_Symbol,1.0,price,one_lot_margin))
return(inp_lot_fix);
return(normalize_lot((AccountInfoDouble(ACCOUNT_BALANCE)*(inp_lot_risk/100))/ one_lot_margin));
}
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
double normalize_lot(double lt)
{
double lot_step = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
lt = MathFloor(lt / lot_step) * lot_step;
double lot_minimum = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
lt = MathMax(lt, lot_minimum);
return(lt);
}
该 EA 的核心是一个深度学习模型,作为预测引擎。该模型旨在根据对市场数据的综合分析预测价格走势,为交易策略添加强大的预测元素。EA 将这些预测与先进的技术指标(包括布林线和相对强弱指数 (RSI))相结合,生成高置信度的交易信号。
EA 的方法包含几个主要特点:
- 持续学习:机器学习模型和技术指标都会进行实时优化。这使得 EA 能够迅速适应不断变化的市场动态,并随着时间的推移不断提高其性能。
- 智能风险管理:EA 采用复杂的风险评估框架,利用动态头寸大小和波动率指标来精确设置止损和止盈。这种方法旨在根据当前市场条件优化风险回报率。
- 多方面的退出策略:该系统采用多种先进的退出方法,允许对未结头寸进行细致入微的管理,以最大限度地提高利润,同时最大限度地减少潜在损失。
- 市场情绪分析:EA 采用自然语言处理技术,从新闻和社交媒体中分析市场情绪,确保交易的执行与更广泛的市场趋势保持一致。

通过对苹果股票数据进行全面的回溯测试,我们对该智能交易系统(EA)的性能进行了深度评估。测试结果显示出显著的盈利能力,尤其是在风险调整后的回报率方面表现突出。然而,分析也暴露了系统在缩水期的不足,这表明现有的风险管理策略仍有优化空间,未来可以通过进一步调整来提升系统的稳定性和抗风险能力。
三、观点总结
本文展示了一款针对股市交易的创新型智能交易系统(EA),专注于苹果这类科技股的高效交易策略。该系统将前沿的机器学习技术与深度技术分析相结合,旨在以更高的精准度和适应性应对复杂多变的股票市场环境。
- 机器学习与技术分析的结合:文章强调了将机器学习模型与传统技术指标(如 SMA 和 EMA)相结合的重要性,以提高交易决策的准确性。
- 持续优化的必要性:指出了定期优化指标和交易参数对于应对市场变化和提高系统性能的重要性。
- 风险管理:文风险管理是交易策略的关键组成部分,包括动态头寸大小和精确的止损/止盈设置。
- 多样化的退出策略:实施多种退出方法很重要,以便更好地管理开放头寸并最大化利润。
- 市场情绪分析:利用自然语言处理技术分析市场情绪的潜力,以确保交易决策与市场趋势一致。
- 实际表现与潜在改进:文章通过回溯测试展示了系统的盈利潜力,同时指出了存在的缩水期,表明还有改进的余地。
- 适应性与未来潜力:该系统具有适应其他金融工具的潜力,并可作为当前和未来算法交易系统的基础。
您可以从这里下载MQL5全脚本压缩包:SE_v9.zip
下载地址:https://www.laoyulaoyu.com/doc/SE_v9.zip

感谢您阅读到最后,希望这篇文章为您带来了新的启发和实用的知识!如果觉得有帮助,请不吝点赞和分享,您的支持是我持续创作的动力。祝您投资顺利,收益长虹!如果对文中内容有任何疑问,欢迎留言,我会尽快回复!
本文内容仅限技术探讨和学习,不构成任何投资建议。
Be First to Comment