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);
}
//+------------------------------------------------------------------+
//| 程序结束 |
//+------------------------------------------------------------------+