MT4虚拟马丁策略EA 只交易特定的层数
马丁格尔策略本质上是一种逆势加仓的交易方法,与趋势交易原则相违背。尽管该策略最终必然面临爆仓风险,但许多交易者(包括我在内)尝试通过各种方法来延缓爆仓的发生。其中最常见的是采用跟单机制来实施马丁策略,具体包括:
仅在浮亏时跟单马丁加仓
缩小倍数
设置加仓层数限制等
通过数据分析,我们发现马丁策略的前几层仓位从长期来看始终呈现亏损状态。举例说明:假设一个马丁策略按照以下6个层级加仓:
1层:0.01手
2层:0.02手
3层:0.03手
4层:0.04手
5层:0.05手
6层:0.06手
观察发现,无论最终是在第2层、第3层还是第6层平仓获利,首层的0.01手仓位始终处于亏损状态。基于这个统计,我们在跟单操作中采取了过滤首层仓位的优化方案,即不跟单0.01手的初始仓位。这样调整后,跟单账户避免了首层仓位的系统性亏损,反而比信号源账户获得了更好的收益表现。
本ea就解决这个问题,虚拟下单,然后通过参数设置,实际下单层数。
这种优化方法的本质是通过剔除统计上确定亏损的仓位层级,来改善马丁策略的整体风险收益比。
核心架构
采用双轨制仓位管理系统:
虚拟仓位:模拟马丁加仓策略,作为信号发生器
实际仓位:仅在特定虚拟层级执行真实交易
完整参数列表
基础参数
| 参数名 | 类型 | 说明 |
|---|---|---|
| MagicNumber | int | EA唯一标识符 |
| TradeDirection | enum | 交易方向(BUY_ONLY/SELL_ONLY/BOTH) |
虚拟仓位参数
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| BaseLotSize | double | 0.01 | 初始手数设置 |
| VirtualLotMultiplier | double | 1.06 | 虚拟加仓倍数 |
| VirtualStepPoints | int | 100 | 加仓间隔(点) |
| MaxVirtualLevels | int | 100 | 最大加仓次数 |
| VirtualTakeProfit | int | 500 | 虚拟整体盈利点数(0表示不设止盈) |
| VirtualStopLoss | int | 500 | 虚拟整体止损点数(0表示不设止损) |
实际仓位参数
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| ActualTradeLevel1 | int | 1 | // 实际开仓层级1(0=禁用) |
| ActualTradeLevel2 | int | 3 | // 实际开仓层级2(0=禁用) |
| ActualTradeLevel3 | int | 5 | // 实际开仓层级3(0=禁用) |
| ActualTradeLevel4 | int | 0 | // 实际开仓层级4(0=禁用) |
| FollowVirtualTP | bool | true | 跟随虚拟止盈 |
| FollowVirtualSL | bool | true | 跟随虚拟止损 |
| ActualTotalTP | int | 500 | 实际整体盈利点数(0=禁用) |
| ActualTotalSL | int | 500 | 实际整体止损点数(0=禁用) |
移动止损参数
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| UseTrailingStop | bool | true | 启用移动止损 |
| TrailingStartPoints | int | 200 | 启动移动止损的盈利点数 |
| TrailingStepPoints | int | 50 | 移动步长(点) |
| TrailingStopPoints | int | 100 | 止损距离(点) |
工作流程
虚拟仓位引擎:
持续监控价格变动
在图表上显示虚拟订单
按马丁策略规则计算虚拟加仓
维护虚拟仓位状态和盈亏
实际交易触发:
当虚拟仓位达到用户预设的层级(如3/5/7层)时
执行真实交易开仓
风险控制:
独立计算虚拟和实际仓位的整体盈亏
支持固定止盈止损和移动止损
达到任一平仓条件时全部平仓
移动止损:
盈利达标后激活
按设定步长和距离跟踪价格
只向有利方向移动
初步代码
//+------------------------------------------------------------------+
//| Virtual Martingale EA |
//| 虚拟马丁策略EA |
//+------------------------------------------------------------------+
#property copyright "Virtual Martingale Strategy"
#property version "1.00"
#property strict
//+------------------------------------------------------------------+
//| 枚举定义 |
//+------------------------------------------------------------------+
enum ENUM_TRADE_DIRECTION
{
BUY_ONLY, // 仅买入
SELL_ONLY, // 仅卖出
BOTH // 双向交易
};
//+------------------------------------------------------------------+
//| 输入参数 |
//+------------------------------------------------------------------+
// 基础参数
input int MagicNumber = 888888; // EA唯一标识符
input ENUM_TRADE_DIRECTION TradeDirection = BOTH; // 交易方向
// 虚拟仓位参数
input double BaseLotSize = 0.01; // 初始手数
input double VirtualLotMultiplier = 1.06; // 虚拟加仓倍数
input int VirtualStepPoints = 100; // 加仓间隔(点)
input int MaxVirtualLevels = 100; // 最大加仓次数
input int VirtualTakeProfit = 500; // 虚拟整体盈利点数
input int VirtualStopLoss = 500; // 虚拟整体止损点数
// 实际仓位参数
input int ActualTradeLevel1 = 1; // 实际开仓层级1(0=禁用)
input int ActualTradeLevel2 = 3; // 实际开仓层级2(0=禁用)
input int ActualTradeLevel3 = 5; // 实际开仓层级3(0=禁用)
input int ActualTradeLevel4 = 0; // 实际开仓层级4(0=禁用)
input bool FollowVirtualTP = true; // 跟随虚拟止盈
input bool FollowVirtualSL = true; // 跟随虚拟止损
input int ActualTotalTP = 500; // 实际整体盈利点数(0=禁用)
input int ActualTotalSL = 500; // 实际整体止损点数(0=禁用)
// 移动止损参数
input bool UseTrailingStop = true; // 启用移动止损
input int TrailingStartPoints = 200; // 启动移动止损的盈利点数
input int TrailingStepPoints = 50; // 移动步长(点)
input int TrailingStopPoints = 100; // 止损距离(点)
// 显示参数
input bool ShowInfoPanel = true; // 显示信息面板
input int InfoPanelX = 20; // 信息面板X坐标
input int InfoPanelY = 30; // 信息面板Y坐标
//+------------------------------------------------------------------+
//| 虚拟订单结构 |
//+------------------------------------------------------------------+
struct VirtualOrder
{
int level; // 层级
int type; // 订单类型 (OP_BUY/OP_SELL)
double lots; // 手数
double openPrice; // 开仓价格
double profit; // 当前盈亏
datetime openTime; // 开仓时间
bool isActive; // 是否激活
};
//+------------------------------------------------------------------+
//| 全局变量 |
//+------------------------------------------------------------------+
// 虚拟仓位相关
VirtualOrder virtualOrders[100]; // 虚拟订单数组
int virtualOrderCount = 0; // 虚拟订单数量
double virtualTotalProfit = 0; // 虚拟总盈亏
double virtualWeightedAvgPrice = 0; // 虚拟持仓均价
double virtualTotalLots = 0; // 虚拟总手数
bool virtualPositionActive = false; // 虚拟仓位状态
int currentVirtualLevel = 0; // 当前虚拟层级
double lastVirtualPrice = 0; // 上次虚拟开仓价格
int virtualDirection = 0; // 虚拟仓位方向 (1=买入, -1=卖出)
// 实际交易相关
int actualTradeCount = 0; // 实际交易数量
double actualTotalProfit = 0; // 实际总盈亏
double trailingStopLevel = 0; // 移动止损水平
bool trailingActive = false; // 移动止损激活状态
// 触发标志
bool level1Triggered = false; // 层级1触发标志
bool level2Triggered = false; // 层级2触发标志
bool level3Triggered = false; // 层级3触发标志
bool level4Triggered = false; // 层级4触发标志
// 其他
datetime lastTickTime = 0; // 上次tick时间
string panelObjectName = "VirtualMartingalePanel"; // 面板对象名
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
Print("虚拟马丁策略EA启动");
// 初始化虚拟订单数组
for(int i = 0; i < 100; i++)
{
virtualOrders[i].isActive = false;
virtualOrders[i].level = 0;
virtualOrders[i].lots = 0;
virtualOrders[i].openPrice = 0;
virtualOrders[i].profit = 0;
virtualOrders[i].type = -1;
virtualOrders[i].openTime = 0;
}
// 参数验证
if(BaseLotSize <= 0)
{
Print("错误:基础手数必须大于0");
return(INIT_PARAMETERS_INCORRECT);
}
if(VirtualLotMultiplier <= 1)
{
Print("错误:虚拟加仓倍数必须大于1");
return(INIT_PARAMETERS_INCORRECT);
}
if(VirtualStepPoints <= 0)
{
Print("错误:加仓间隔必须大于0");
return(INIT_PARAMETERS_INCORRECT);
}
if(MaxVirtualLevels <= 0)
{
Print("错误:最大加仓次数必须大于0");
return(INIT_PARAMETERS_INCORRECT);
}
// 初始化变量
virtualOrderCount = 0;
virtualTotalProfit = 0;
virtualWeightedAvgPrice = 0;
virtualTotalLots = 0;
virtualPositionActive = false;
currentVirtualLevel = 0;
lastVirtualPrice = 0;
virtualDirection = 0;
actualTradeCount = 0;
actualTotalProfit = 0;
trailingStopLevel = 0;
trailingActive = false;
// 重置触发标志
level1Triggered = false;
level2Triggered = false;
level3Triggered = false;
level4Triggered = false;
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Print("虚拟马丁策略EA停止,原因:", reason);
// 删除图表对象
if(ObjectFind(panelObjectName) >= 0)
{
ObjectDelete(panelObjectName);
}
// 清理资源
Comment("");
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// 更新虚拟仓位状态
UpdateVirtualPositions();
// 检查虚拟仓位开仓条件
CheckVirtualEntry();
// 检查实际交易开仓条件
CheckActualTradeEntry();
// 检查平仓条件
CheckCloseConditions();
// 更新移动止损
if(UseTrailingStop)
UpdateTrailingStop();
// 显示信息面板
if(ShowInfoPanel)
ShowInfoPanel();
lastTickTime = TimeCurrent();
}
//+------------------------------------------------------------------+
//| 更新虚拟仓位状态 |
//+------------------------------------------------------------------+
void UpdateVirtualPositions()
{
virtualTotalProfit = 0;
virtualTotalLots = 0;
virtualWeightedAvgPrice = 0;
double totalValue = 0;
for(int i = 0; i < virtualOrderCount; i++)
{
if(virtualOrders[i].isActive)
{
double currentPrice = (virtualOrders[i].type == OP_BUY) ? Bid : Ask;
double pointValue = MarketInfo(Symbol(), MODE_TICKVALUE);
if(virtualOrders[i].type == OP_BUY)
{
virtualOrders[i].profit = (currentPrice - virtualOrders[i].openPrice) * virtualOrders[i].lots * pointValue / Point;
}
else
{
virtualOrders[i].profit = (virtualOrders[i].openPrice - currentPrice) * virtualOrders[i].lots * pointValue / Point;
}
virtualTotalProfit += virtualOrders[i].profit;
virtualTotalLots += virtualOrders[i].lots;
totalValue += virtualOrders[i].openPrice * virtualOrders[i].lots;
}
}
if(virtualTotalLots > 0)
{
virtualWeightedAvgPrice = totalValue / virtualTotalLots;
virtualPositionActive = true;
}
else
{
virtualPositionActive = false;
}
}
//+------------------------------------------------------------------+
//| 检查虚拟仓位开仓条件 |
//+------------------------------------------------------------------+
void CheckVirtualEntry()
{
if(!virtualPositionActive)
{
// 首次开仓
if(TradeDirection == BUY_ONLY || TradeDirection == BOTH)
{
OpenVirtualOrder(OP_BUY, BaseLotSize, Ask, 1);
}
else if(TradeDirection == SELL_ONLY)
{
OpenVirtualOrder(OP_SELL, BaseLotSize, Bid, 1);
}
}
else
{
// 检查加仓条件
if(currentVirtualLevel < MaxVirtualLevels)
{
double currentPrice = (virtualDirection == 1) ? Bid : Ask;
double priceDiff = MathAbs(currentPrice - lastVirtualPrice);
if(priceDiff >= VirtualStepPoints * Point)
{
// 计算下一层级手数
double nextLotSize = BaseLotSize * MathPow(VirtualLotMultiplier, currentVirtualLevel);
// 确保不超过最大手数限制
double maxLot = MarketInfo(Symbol(), MODE_MAXLOT);
double minLot = MarketInfo(Symbol(), MODE_MINLOT);
double lotStep = MarketInfo(Symbol(), MODE_LOTSTEP);
if(nextLotSize > maxLot)
nextLotSize = maxLot;
if(nextLotSize < minLot)
nextLotSize = minLot;
// 规范化手数
nextLotSize = NormalizeDouble(nextLotSize / lotStep, 0) * lotStep;
// 开设虚拟加仓订单
int orderType = (virtualDirection == 1) ? OP_BUY : OP_SELL;
double orderPrice = (virtualDirection == 1) ? Ask : Bid;
OpenVirtualOrder(orderType, nextLotSize, orderPrice, currentVirtualLevel + 1);
}
}
}
}
//+------------------------------------------------------------------+
//| 开设虚拟订单 |
//+------------------------------------------------------------------+
void OpenVirtualOrder(int type, double lots, double price, int level)
{
if(virtualOrderCount >= 100)
{
Print("警告:虚拟订单数量已达上限");
return;
}
virtualOrders[virtualOrderCount].level = level;
virtualOrders[virtualOrderCount].type = type;
virtualOrders[virtualOrderCount].lots = lots;
virtualOrders[virtualOrderCount].openPrice = price;
virtualOrders[virtualOrderCount].profit = 0;
virtualOrders[virtualOrderCount].openTime = TimeCurrent();
virtualOrders[virtualOrderCount].isActive = true;
virtualOrderCount++;
currentVirtualLevel = level;
lastVirtualPrice = price;
virtualDirection = (type == OP_BUY) ? 1 : -1;
Print("虚拟订单开仓:层级", level, " 类型", (type == OP_BUY ? "买入" : "卖出"),
" 手数", DoubleToStr(lots, 2), " 价格", DoubleToStr(price, Digits));
}
//+------------------------------------------------------------------+
//| 检查实际交易开仓条件 |
//+------------------------------------------------------------------+
void CheckActualTradeEntry()
{
if(!virtualPositionActive)
return;
// 检查层级1
if(ActualTradeLevel1 > 0 && currentVirtualLevel >= ActualTradeLevel1 && !level1Triggered)
{
ExecuteActualTrade("Level1");
level1Triggered = true;
}
// 检查层级2
if(ActualTradeLevel2 > 0 && currentVirtualLevel >= ActualTradeLevel2 && !level2Triggered)
{
ExecuteActualTrade("Level2");
level2Triggered = true;
}
// 检查层级3
if(ActualTradeLevel3 > 0 && currentVirtualLevel >= ActualTradeLevel3 && !level3Triggered)
{
ExecuteActualTrade("Level3");
level3Triggered = true;
}
// 检查层级4
if(ActualTradeLevel4 > 0 && currentVirtualLevel >= ActualTradeLevel4 && !level4Triggered)
{
ExecuteActualTrade("Level4");
level4Triggered = true;
}
}
//+------------------------------------------------------------------+
//| 执行实际交易 |
//+------------------------------------------------------------------+
void ExecuteActualTrade(string levelName)
{
// 计算实际开仓手数
double actualLots = BaseLotSize;
// 规范化手数
double minLot = MarketInfo(Symbol(), MODE_MINLOT);
double maxLot = MarketInfo(Symbol(), MODE_MAXLOT);
double lotStep = MarketInfo(Symbol(), MODE_LOTSTEP);
if(actualLots < minLot)
actualLots = minLot;
if(actualLots > maxLot)
actualLots = maxLot;
actualLots = NormalizeDouble(actualLots / lotStep, 0) * lotStep;
// 执行实际交易
int orderType = (virtualDirection == 1) ? OP_BUY : OP_SELL;
double orderPrice = (virtualDirection == 1) ? Ask : Bid;
int slippage = 3;
string comment = "VM_" + levelName + "_" + IntegerToString(currentVirtualLevel);
int ticket = OrderSend(Symbol(), orderType, actualLots, orderPrice, slippage, 0, 0,
comment, MagicNumber, 0, clrBlue);
if(ticket > 0)
{
actualTradeCount++;
Print("实际交易开仓:票据", ticket, " 层级", levelName, " 虚拟层级", currentVirtualLevel,
" 类型", (orderType == OP_BUY ? "买入" : "卖出"),
" 手数", DoubleToStr(actualLots, 2), " 价格", DoubleToStr(orderPrice, Digits));
}
else
{
int error = GetLastError();
Print("实际交易开仓失败:", error, " 描述:", ErrorDescription(error));
}
}
//+------------------------------------------------------------------+
//| 检查是否存在实际交易 |
//+------------------------------------------------------------------+
bool IsActualTradeOpen()
{
for(int i = 0; i < OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS) && OrderSymbol() == Symbol() &&
OrderMagicNumber() == MagicNumber)
{
return(true);
}
}
return(false);
}
//+------------------------------------------------------------------+
//| 计算实际交易总盈亏 |
//+------------------------------------------------------------------+
double GetActualTotalProfit()
{
double totalProfit = 0;
for(int i = 0; i < OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS) && OrderSymbol() == Symbol() &&
OrderMagicNumber() == MagicNumber)
{
totalProfit += OrderProfit() + OrderSwap() + OrderCommission();
}
}
return(totalProfit);
}
//+------------------------------------------------------------------+
//| 检查平仓条件 |
//+------------------------------------------------------------------+
void CheckCloseConditions()
{
if(!virtualPositionActive)
return;
actualTotalProfit = GetActualTotalProfit();
bool shouldClose = false;
string closeReason = "";
// 检查虚拟止盈
if(VirtualTakeProfit > 0)
{
double virtualTPValue = VirtualTakeProfit * Point * MarketInfo(Symbol(), MODE_TICKVALUE);
if(virtualTotalProfit >= virtualTPValue)
{
shouldClose = true;
closeReason = "虚拟止盈";
}
}
// 检查虚拟止损
if(VirtualStopLoss > 0)
{
double virtualSLValue = -VirtualStopLoss * Point * MarketInfo(Symbol(), MODE_TICKVALUE);
if(virtualTotalProfit <= virtualSLValue)
{
shouldClose = true;
closeReason = "虚拟止损";
}
}
// 检查实际止盈
if(ActualTotalTP > 0 && !FollowVirtualTP)
{
double actualTPValue = ActualTotalTP * Point * MarketInfo(Symbol(), MODE_TICKVALUE);
if(actualTotalProfit >= actualTPValue)
{
shouldClose = true;
closeReason = "实际止盈";
}
}
// 检查实际止损
if(ActualTotalSL > 0 && !FollowVirtualSL)
{
double actualSLValue = -ActualTotalSL * Point * MarketInfo(Symbol(), MODE_TICKVALUE);
if(actualTotalProfit <= actualSLValue)
{
shouldClose = true;
closeReason = "实际止损";
}
}
if(shouldClose)
{
CloseAllPositions(closeReason);
}
}
//+------------------------------------------------------------------+
//| 关闭所有仓位 |
//+------------------------------------------------------------------+
void CloseAllPositions(string reason)
{
Print("开始平仓:", reason);
// 关闭所有实际交易
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS) && OrderSymbol() == Symbol() &&
OrderMagicNumber() == MagicNumber)
{
double closePrice = (OrderType() == OP_BUY) ? Bid : Ask;
bool result = OrderClose(OrderTicket(), OrderLots(), closePrice, 3, clrRed);
if(result)
{
Print("实际交易平仓:票据", OrderTicket(), " 盈亏", DoubleToStr(OrderProfit(), 2));
}
else
{
int error = GetLastError();
Print("实际交易平仓失败:", error, " 描述:", ErrorDescription(error));
}
}
}
// 清除虚拟仓位
ClearVirtualPositions();
Print("平仓完成:", reason, " 虚拟盈亏", DoubleToStr(virtualTotalProfit, 2),
" 实际盈亏", DoubleToStr(actualTotalProfit, 2));
}
//+------------------------------------------------------------------+
//| 清除虚拟仓位 |
//+------------------------------------------------------------------+
void ClearVirtualPositions()
{
for(int i = 0; i < virtualOrderCount; i++)
{
virtualOrders[i].isActive = false;
virtualOrders[i].level = 0;
virtualOrders[i].lots = 0;
virtualOrders[i].openPrice = 0;
virtualOrders[i].profit = 0;
virtualOrders[i].type = -1;
virtualOrders[i].openTime = 0;
}
virtualOrderCount = 0;
virtualTotalProfit = 0;
virtualWeightedAvgPrice = 0;
virtualTotalLots = 0;
virtualPositionActive = false;
currentVirtualLevel = 0;
lastVirtualPrice = 0;
virtualDirection = 0;
actualTradeCount = 0;
actualTotalProfit = 0;
trailingStopLevel = 0;
trailingActive = false;
// 重置触发标志
level1Triggered = false;
level2Triggered = false;
level3Triggered = false;
level4Triggered = false;
}
//+------------------------------------------------------------------+
//| 更新移动止损 |
//+------------------------------------------------------------------+
void UpdateTrailingStop()
{
if(!virtualPositionActive || actualTradeCount == 0)
return;
double currentProfit = (FollowVirtualTP && FollowVirtualSL) ? virtualTotalProfit : actualTotalProfit;
double startValue = TrailingStartPoints * Point * MarketInfo(Symbol(), MODE_TICKVALUE);
// 检查是否达到启动移动止损的条件
if(currentProfit >= startValue)
{
if(!trailingActive)
{
trailingActive = true;
trailingStopLevel = currentProfit - TrailingStopPoints * Point * MarketInfo(Symbol(), MODE_TICKVALUE);
Print("移动止损激活:当前盈利", DoubleToStr(currentProfit, 2),
" 止损水平", DoubleToStr(trailingStopLevel, 2));
}
else
{
// 更新移动止损水平
double newStopLevel = currentProfit - TrailingStopPoints * Point * MarketInfo(Symbol(), MODE_TICKVALUE);
if(newStopLevel > trailingStopLevel + TrailingStepPoints * Point * MarketInfo(Symbol(), MODE_TICKVALUE))
{
trailingStopLevel = newStopLevel;
Print("移动止损更新:新止损水平", DoubleToStr(trailingStopLevel, 2));
}
}
// 检查是否触发移动止损
if(currentProfit <= trailingStopLevel)
{
CloseAllPositions("移动止损触发");
}
}
}
//+------------------------------------------------------------------+
//| 显示信息面板 |
//+------------------------------------------------------------------+
void ShowInfoPanel()
{
string info = "";
info += "==== 虚拟马丁策略EA ====\n";
info += "交易品种:" + Symbol() + "\n";
info += "账户余额:" + DoubleToStr(AccountBalance(), 2) + "\n";
info += "账户净值:" + DoubleToStr(AccountEquity(), 2) + "\n";
info += "------------------------\n";
info += "虚拟仓位状态:" + (virtualPositionActive ? "激活" : "未激活") + "\n";
info += "当前虚拟层级:" + IntegerToString(currentVirtualLevel) + "\n";
info += "虚拟订单数量:" + IntegerToString(virtualOrderCount) + "\n";
info += "虚拟总手数:" + DoubleToStr(virtualTotalLots, 2) + "\n";
if(virtualPositionActive)
{
info += "虚拟均价:" + DoubleToStr(virtualWeightedAvgPrice, Digits) + "\n";
info += "虚拟方向:" + (virtualDirection == 1 ? "买入" : "卖出") + "\n";
}
info += "虚拟总盈亏:" + DoubleToStr(virtualTotalProfit, 2) + "\n";
info += "------------------------\n";
info += "实际交易数量:" + IntegerToString(actualTradeCount) + "\n";
info += "实际总盈亏:" + DoubleToStr(actualTotalProfit, 2) + "\n";
info += "移动止损:" + (trailingActive ? "激活" : "未激活") + "\n";
if(trailingActive)
{
info += "止损水平:" + DoubleToStr(trailingStopLevel, 2) + "\n";
}
info += "------------------------\n";
info += "触发状态:\n";
info += "Level1(" + IntegerToString(ActualTradeLevel1) + "):" + (level1Triggered ? "已触发" : "未触发") + "\n";
info += "Level2(" + IntegerToString(ActualTradeLevel2) + "):" + (level2Triggered ? "已触发" : "未触发") + "\n";
info += "Level3(" + IntegerToString(ActualTradeLevel3) + "):" + (level3Triggered ? "已触发" : "未触发") + "\n";
info += "Level4(" + IntegerToString(ActualTradeLevel4) + "):" + (level4Triggered ? "已触发" : "未触发") + "\n";
info += "------------------------\n";
info += "最后更新:" + TimeToStr(TimeCurrent(), TIME_SECONDS) + "\n";
Comment(info);
}
//+------------------------------------------------------------------+
//| 获取错误描述 |
//+------------------------------------------------------------------+
string ErrorDescription(int error)
{
switch(error)
{
case 0: return("无错误");
case 1: return("无错误,但结果未知");
case 2: return("一般错误");
case 3: return("无效的参数");
case 4: return("交易服务器繁忙");
case 5: return("旧版本的客户端");
case 6: return("没有连接到交易服务器");
case 7: return("没有足够的权限");
case 8: return("频繁的请求");
case 9: return("不兼容的操作");
case 64: return("账户被禁用");
case 65: return("无效的账户");
case 128: return("交易超时");
case 129: return("无效的价格");
case 130: return("无效的停止");
case 131: return("无效的交易量");
case 132: return("市场关闭");
case 133: return("交易被禁用");
case 134: return("没有足够的资金");
case 135: return("价格改变");
case 136: return("离线报价");
case 137: return("经纪商繁忙");
case 138: return("重新报价");
case 139: return("订单被锁定");
case 140: return("只允许买入");
case 141: return("允许的订单数量已达上限");
case 145: return("修改被禁用");
case 146: return("上下文繁忙");
case 147: return("到期时间被禁用");
case 148: return("订单数量已达上限");
default: return("未知错误 " + IntegerToString(error));
}
}
//+------------------------------------------------------------------+
//| 计算点值 |
//+------------------------------------------------------------------+
double GetPointValue()
{
double tickValue = MarketInfo(Symbol(), MODE_TICKVALUE);
double tickSize = MarketInfo(Symbol(), MODE_TICKSIZE);
return(tickValue * Point / tickSize);
}
//+------------------------------------------------------------------+
//| 获取虚拟仓位详细信息 |
//+------------------------------------------------------------------+
string GetVirtualPositionDetails()
{
string details = "";
if(!virtualPositionActive)
{
return("无虚拟仓位");
}
details += "虚拟仓位详情:\n";
details += "层级\t手数\t\t开仓价\t\t盈亏\n";
for(int i = 0; i < virtualOrderCount; i++)
{
if(virtualOrders[i].isActive)
{
details += IntegerToString(virtualOrders[i].level) + "\t";
details += DoubleToStr(virtualOrders[i].lots, 2) + "\t\t";
details += DoubleToStr(virtualOrders[i].openPrice, Digits) + "\t\t";
details += DoubleToStr(virtualOrders[i].profit, 2) + "\n";
}
}
return(details);
}
//+------------------------------------------------------------------+
//| 重置EA状态 |
//+------------------------------------------------------------------+
void ResetEAState()
{
Print("重置EA状态");
ClearVirtualPositions();
}
//+------------------------------------------------------------------+
//| 检查账户状态 |
//+------------------------------------------------------------------+
bool CheckAccountStatus()
{
if(!IsConnected())
{
Print("警告:与交易服务器连接中断");
return(false);
}
if(!IsTradeAllowed())
{
Print("警告:交易被禁用");
return(false);
}
if(AccountFreeMargin() < BaseLotSize * MarketInfo(Symbol(), MODE_MARGINREQUIRED))
{
Print("警告:可用保证金不足");
return(false);
}
return(true);
}
//+------------------------------------------------------------------+
//| 程序结束 |
//+------------------------------------------------------------------+💡 精彩内容推荐
✍️ 楼主最新发布
- •
- •
- •
- •
- •
- •
🔗 您可能感兴趣
- •
- •
🔐
请登录后参与评论
注册满12小时后评论,即可解锁附件下载
立即登录
