老交易员一看就懂。
这个系统我部署到了云服务器上面,云服务器的密码和我账户的密码都只有我老婆知道,目前已经稳定运行了一年了,对我非常非常有效,用处极大。
不让上传EA附件,代码分享给大家
//+------------------------------------------------------------------+
//| RiskEA.mq4 |
//| Copyright 2023, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
// 输入参数
input string SymbolFilter = "EURUSD"; // 允许交易的品种
input double MaxTotalVolume = 10; // 最大总持仓手数
input double MaxDailyLossPercent = 2; // 最大单日亏损比例(%)
// 全局变量
datetime LastCheckTime;
datetime CurrentDayStart;
bool AllowTrading = true;
//+------------------------------------------------------------------+
//| 初始化函数 |
//+------------------------------------------------------------------+
int OnInit()
{
CurrentDayStart = GetDayStart(TimeCurrent());
LastCheckTime = TimeCurrent();
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| 主函数 |
//+------------------------------------------------------------------+
void OnTick()
{
// 每分钟检查一次交易日切换
if(TimeCurrent() >= LastCheckTime + 60)
{
datetime newDayStart = GetDayStart(TimeCurrent());
if(newDayStart != CurrentDayStart)
{
CurrentDayStart = newDayStart;
AllowTrading = true; // 新交易日重置交易权限
}
LastCheckTime = TimeCurrent();
}
// 风控检查1:交易品种过滤
CheckSymbolFilter();
// 风控检查2:最大持仓限制
CheckMaxVolume();
// 风控检查3:最大亏损限制
if(!CheckDailyLoss())
{
CloseAllOrders();
AllowTrading = false;
}
// 如果禁止交易则关闭所有订单
if(!AllowTrading)
{
CloseAllOrders();
}
}
//+------------------------------------------------------------------+
//| 交易品种过滤检查 |
//+------------------------------------------------------------------+
void CheckSymbolFilter()
{
for(int i=OrdersTotal()-1; i>=0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() != SymbolFilter)
{
CloseOrder(OrderTicket());
}
}
}
}
//+------------------------------------------------------------------+
//| 最大持仓检查 |
//+------------------------------------------------------------------+
void CheckMaxVolume()
{
double totalVolume = 0;
for(int i=OrdersTotal()-1; i>=0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
totalVolume += OrderLots();
}
}
if(totalVolume > MaxTotalVolume)
{
CloseAllOrders();
}
}
//+------------------------------------------------------------------+
//| 单日亏损检查 |
//+------------------------------------------------------------------+
bool CheckDailyLoss()
{
if(!AllowTrading) return false;
double dailyProfit = 0;
datetime dayStart = GetDayStart(TimeCurrent());
datetime dayEnd = dayStart + 86400;
// 计算历史订单盈亏
for(int i=OrdersHistoryTotal()-1; i>=0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
{
if(OrderCloseTime() >= dayStart && OrderCloseTime() < dayEnd)
{
dailyProfit += OrderProfit() + OrderSwap() + OrderCommission();
}
}
}
// 计算当前持仓浮动盈亏
for(int i=OrdersTotal()-1; i>=0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
dailyProfit += OrderProfit() + OrderSwap() + OrderCommission();
}
}
// 计算亏损比例
double equity = AccountEquity();
double lossPercent = (-dailyProfit) / equity * 100;
return (lossPercent < MaxDailyLossPercent);
}
//+------------------------------------------------------------------+
//| 获取当日开始时间 |
//+------------------------------------------------------------------+
datetime GetDayStart(datetime time)
{
MqlDateTime mdt;
TimeToStruct(time, mdt);
mdt.hour = 0;
mdt.min = 0;
mdt.sec = 0;
return StructToTime(mdt);
}
//+------------------------------------------------------------------+
//| 关闭指定订单 |
//+------------------------------------------------------------------+
void CloseOrder(int ticket)
{
if(OrderSelect(ticket, SELECT_BY_TICKET))
{
if(OrderType() == OP_BUY)
OrderClose(ticket, OrderLots(), Bid, 3);
else if(OrderType() == OP_SELL)
OrderClose(ticket, OrderLots(), Ask, 3);
else
OrderDelete(ticket);
}
}
//+------------------------------------------------------------------+
//| 关闭所有订单 |
//+------------------------------------------------------------------+
void CloseAllOrders()
{
for(int i=OrdersTotal()-1; i>=0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
CloseOrder(OrderTicket());
}
}
}
//+------------------------------------------------------------------+