设为首页 收藏本站 切换语言 切换语言

源码自己拿

| 发表于 5 小时前 | 显示全部楼层 |复制链接
//+------------------------------------------------------------------+
//|                                            GoldenCrossEA.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 bool EnableGoldenCross = true;                    // 启用金叉死叉模式
input int MagicNumber = 12345;                         // 金叉模式魔术码
input int TradeDirection = 0;                          // 金叉交易方向: 0-多空都做, 1-只做多, 2-只做空
input double FirstLotSize = 0.01;                      // 金叉模式首单手数

//--- 移动平均线参数
input int FastMAPeriod = 5;                            // 金叉快线周期
input int SlowMAPeriod = 20;                           // 金叉慢线周期

//--- 时间控制参数
input bool EnableTimeControl = false;                  // 启用时间控制
input string StartTime = "00:00";                      // 开始时间 (HH:MM)
input string EndTime = "23:59";                        // 结束时间 (HH:MM)

//--- 加仓参数
input bool EnablePyramid = true;                       // 启用加仓
input int PyramidMode = 0;                             // 加仓模式: 0-顺势加仓, 1-逆势补仓
input double PyramidMultiplier = 1.5;                  // 加仓倍数
input int PyramidInterval = 50;                        // 加仓间隔(点数)
input int MaxPyramidLevel = 5;                         // 最大加仓层数

//--- 平仓参数
input bool EnableFirstOrderProfit = true;              // 启用首单盈利平仓
input int FirstOrderProfitPoints = 100;                // 首单盈利点数

input bool EnableUnidirectionalProfit = true;          // 启用单边整体盈利平仓
input int UnidirectionalProfitPoints = 200;            // 单边整体盈利点数

input bool EnableTotalProfitClose = true;              // 启用整体盈利平仓
input int TotalProfitPoints = 500;                     // 整体盈利点数(按总持仓手数计算)

//--- 全局变量
double fastMA0, fastMA1, slowMA0, slowMA1;
datetime lastTradeTime = 0;
bool timeControlActive = false;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
    Print("Golden Cross EA with Time Control initialized successfully");
    Print("Pyramid Mode: ", PyramidMode == 0 ? "顺势加仓" : "逆势补仓");
    Print("Time Control: ", EnableTimeControl ? "Enabled" : "Disabled");
    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    Print("EA deinitialized with reason: ", reason);
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
    if(!EnableGoldenCross) return;

    // 更新指标数据
    if(!UpdateMAData()) return;

    // 检查时间控制状态
    CheckTimeControl();

    // 检查平仓条件(始终执行,不受时间控制影响)
    CheckCloseConditions();

    // 只有在允许交易的时间内才执行开仓和加仓
    if(IsTradingAllowed())
    {
        CheckOpenConditions();
        CheckPyramidConditions();
    }
}

//+------------------------------------------------------------------+
//| 检查时间控制状态                                                 |
//+------------------------------------------------------------------+
void CheckTimeControl()
{
    if(!EnableTimeControl)
    {
        timeControlActive = false;
        return;
    }

    int totalOrders = CountOrders();

    // 如果有订单,时间控制不生效
    if(totalOrders > 0)
    {
        timeControlActive = false;
        return;
    }

    // 没有订单时,检查是否在限定时间内
    timeControlActive = IsTradeTime();
}

//+------------------------------------------------------------------+
//| 检查是否允许交易(重命名避免冲突)                               |
//+------------------------------------------------------------------+
bool IsTradingAllowed()
{
    // 如果没有启用时间控制,始终允许交易
    if(!EnableTimeControl) return true;

    // 如果有订单,始终允许交易(等订单结束后再受时间限制)
    if(CountOrders() > 0) return true;

    // 没有订单时,只在交易时间内允许交易
    return timeControlActive;
}

//+------------------------------------------------------------------+
//| 检查交易时间                                                     |
//+------------------------------------------------------------------+
bool IsTradeTime()
{
    datetime current = TimeCurrent();
    int currentHour = TimeHour(current);
    int currentMinute = TimeMinute(current);

    string startHours = StringSubstr(StartTime, 0, 2);
    string startMinutes = StringSubstr(StartTime, 3, 2);
    string endHours = StringSubstr(EndTime, 0, 2);
    string endMinutes = StringSubstr(EndTime, 3, 2);

    int startHour = StrToInteger(startHours);
    int startMinute = StrToInteger(startMinutes);
    int endHour = StrToInteger(endHours);
    int endMinute = StrToInteger(endMinutes);

    int currentTime = currentHour * 100 + currentMinute;
    int startTime = startHour * 100 + startMinute;
    int endTime = endHour * 100 + endMinute;

    if(startTime <= endTime)
        return (currentTime >= startTime && currentTime <= endTime);
    else
        return (currentTime >= startTime || currentTime <= endTime);
}

//+------------------------------------------------------------------+
//| 检查平仓条件                                                     |
//+------------------------------------------------------------------+
void CheckCloseConditions()
{
    // 首单盈利平仓
    if(EnableFirstOrderProfit && CheckFirstOrderProfit())
    {
        CloseAllOrders();
        Print("首单盈利平仓: 达到目标盈利点数 ", FirstOrderProfitPoints, "点");
        return;
    }

    // 单边整体盈利平仓
    if(EnableUnidirectionalProfit)
    {
        if(CheckUnidirectionalProfit(OP_BUY))
        {
            CloseAllOrdersByType(OP_BUY);
            Print("多单整体盈利平仓: 达到目标盈利点数 ", UnidirectionalProfitPoints, "点");
        }
        else if(CheckUnidirectionalProfit(OP_SELL))
        {
            CloseAllOrdersByType(OP_SELL);
            Print("空单整体盈利平仓: 达到目标盈利点数 ", UnidirectionalProfitPoints, "点");
        }
    }

    // 整体盈利平仓(按总持仓手数计算)
    if(EnableTotalProfitClose && CheckTotalProfitPoints())
    {
        CloseAllOrders();
        Print("整体盈利平仓: 达到目标盈利点数 ", TotalProfitPoints, "点");
        return;
    }
}

//+------------------------------------------------------------------+
//| 检查首单盈利条件                                                 |
//+------------------------------------------------------------------+
bool CheckFirstOrderProfit()
{
    for(int i = 0; i < OrdersTotal(); i++)
    {
        if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
        {
            if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
            {
                // 检查是否是首单(手数等于首单手数)
                if(OrderLots() == FirstLotSize)
                {
                    double profitPoints = 0;
                    if(OrderType() == OP_BUY)
                        profitPoints = (Bid - OrderOpenPrice()) / Point;
                    else if(OrderType() == OP_SELL)
                        profitPoints = (OrderOpenPrice() - Ask) / Point;

                    if(profitPoints >= FirstOrderProfitPoints)
                    {
                        Print("首单盈利达标: 订单=", OrderTicket(),
                              " 手数=", OrderLots(),
                              " 盈利点数=", profitPoints);
                        return true;
                    }
                }
            }
        }
    }
    return false;
}

//+------------------------------------------------------------------+
//| 检查单边整体盈利条件                                             |
//+------------------------------------------------------------------+
bool CheckUnidirectionalProfit(int orderType)
{
    double totalProfit = 0;
    double totalLots = 0;

    for(int i = 0; i < OrdersTotal(); i++)
    {
        if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
        {
            if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && OrderType() == orderType)
            {
                totalProfit += OrderProfit() + OrderSwap() + OrderCommission();
                totalLots += OrderLots();
            }
        }
    }

    if(totalLots <= 0) return false;

    // 计算每手平均盈利点数
    double profitPerLotPoints = CalculateProfitPerLotPoints(totalProfit, totalLots);

    if(TimeCurrent() % 60 == 0) // 每分钟打印一次
    {
        string typeStr = (orderType == OP_BUY) ? "多单" : "空单";
        Print(typeStr, "盈利统计: 总盈利=", totalProfit,
              " 总手数=", totalLots,
              " 每手盈利点数=", profitPerLotPoints);
    }

    return (profitPerLotPoints >= UnidirectionalProfitPoints);
}

//+------------------------------------------------------------------+
//| 检查整体盈利点数(按总持仓手数计算)                             |
//+------------------------------------------------------------------+
bool CheckTotalProfitPoints()
{
    double totalProfit = 0;
    double totalLots = 0;
    double totalBuyLots = 0;
    double totalSellLots = 0;

    for(int i = 0; i < OrdersTotal(); i++)
    {
        if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
        {
            if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
            {
                totalProfit += OrderProfit() + OrderSwap() + OrderCommission();
                totalLots += OrderLots();

                if(OrderType() == OP_BUY)
                    totalBuyLots += OrderLots();
                else if(OrderType() == OP_SELL)
                    totalSellLots += OrderLots();
            }
        }
    }

    if(totalLots <= 0) return false;

    // 计算每手平均盈利点数
    double profitPerLotPoints = CalculateProfitPerLotPoints(totalProfit, totalLots);

    // 打印详细盈利信息
    if(TimeCurrent() % 60 == 0) // 每分钟打印一次
    {
        Print("整体盈利统计: 总盈利=", totalProfit,
              " 总手数=", totalLots,
              " 多单手数=", totalBuyLots,
              " 空单手数=", totalSellLots,
              " 每手盈利点数=", profitPerLotPoints);
    }

    return (profitPerLotPoints >= TotalProfitPoints);
}

//+------------------------------------------------------------------+
//| 计算每手平均盈利点数                                             |
//+------------------------------------------------------------------+
double CalculateProfitPerLotPoints(double totalProfit, double totalLots)
{
    if(totalLots <= 0) return 0;

    // 方法1:使用tickvalue计算(更精确)
    double tickValue = MarketInfo(Symbol(), MODE_TICKVALUE);
    double tickSize = MarketInfo(Symbol(), MODE_TICKSIZE);

    if(tickValue > 0 && tickSize > 0)
    {
        // 计算每手平均盈利点数
        double profitPerLot = totalProfit / totalLots;
        double pointsPerLot = (profitPerLot / tickValue) * (Point / tickSize);
        return pointsPerLot;
    }

    // 方法2:简化计算(备用)
    double profitPerLotPoints = totalProfit / totalLots / 10.0; // 近似计算
    return profitPerLotPoints;
}

//+------------------------------------------------------------------+
//| 检查开仓条件                                                     |
//+------------------------------------------------------------------+
void CheckOpenConditions()
{
    // 检查金叉死叉
    bool goldenCross = (fastMA1 <= slowMA1 && fastMA0 > slowMA0);
    bool deadCross = (fastMA1 >= slowMA1 && fastMA0 < slowMA0);

    if(goldenCross && (TradeDirection == 0 || TradeDirection == 1))
    {
        // 检查是否已经有首单
        if(CountOrders(OP_BUY) == 0)
        {
            OpenBuyOrder(FirstLotSize);
            Print("金叉开多单,手数: ", FirstLotSize);
        }
    }
    else if(deadCross && (TradeDirection == 0 || TradeDirection == 2))
    {
        // 检查是否已经有首单
        if(CountOrders(OP_SELL) == 0)
        {
            OpenSellOrder(FirstLotSize);
            Print("死叉开空单,手数: ", FirstLotSize);
        }
    }
}

//+------------------------------------------------------------------+
//| 检查加仓条件                                                     |
//+------------------------------------------------------------------+
void CheckPyramidConditions()
{
    if(!EnablePyramid) return;

    // 多单加仓逻辑
    CheckBuyPyramid();

    // 空单加仓逻辑
    CheckSellPyramid();
}

//+------------------------------------------------------------------+
//| 多单加仓检查                                                     |
//+------------------------------------------------------------------+
void CheckBuyPyramid()
{
    int buyCount = CountOrders(OP_BUY);
    if(buyCount == 0 || buyCount >= MaxPyramidLevel) return;

    double currentPrice = Ask;
    double avgBuyPrice = GetAveragePrice(OP_BUY);
    double lastBuyPrice = GetLastOrderPrice(OP_BUY);

    // 计算价格差异(点数)
    double priceDiffFromLast = (lastBuyPrice - currentPrice) / Point;
    double priceDiffFromAvg = (avgBuyPrice - currentPrice) / Point;

    bool shouldPyramid = false;

    if(PyramidMode == 0) // 顺势加仓模式
    {
        // 顺势加仓:价格继续下跌时加仓(多单成本更低)
        shouldPyramid = (priceDiffFromLast >= PyramidInterval);
    }
    else if(PyramidMode == 1) // 逆势补仓模式
    {
        // 逆势补仓:当多单亏损达到间隔时补仓
        double currentProfitPoints = (currentPrice - avgBuyPrice) / Point;
        shouldPyramid = (currentProfitPoints <= -PyramidInterval);
    }

    if(shouldPyramid)
    {
        double pyramidLot = CalculatePyramidLot(OP_BUY);
        if(pyramidLot > 0)
        {
            OpenBuyOrder(pyramidLot);
            string modeStr = (PyramidMode == 0) ? "顺势加仓" : "逆势补仓";
            Print("多单", modeStr, " #", buyCount + 1, " 手数:", pyramidLot);
        }
    }
}

//+------------------------------------------------------------------+
//| 空单加仓检查                                                     |
//+------------------------------------------------------------------+
void CheckSellPyramid()
{
    int sellCount = CountOrders(OP_SELL);
    if(sellCount == 0 || sellCount >= MaxPyramidLevel) return;

    double currentPrice = Bid;
    double avgSellPrice = GetAveragePrice(OP_SELL);
    double lastSellPrice = GetLastOrderPrice(OP_SELL);

    // 计算价格差异(点数)
    double priceDiffFromLast = (currentPrice - lastSellPrice) / Point;
    double priceDiffFromAvg = (currentPrice - avgSellPrice) / Point;

    bool shouldPyramid = false;

    if(PyramidMode == 0) // 顺势加仓模式
    {
        // 顺势加仓:价格继续上涨时加仓(空单成本更高)
        shouldPyramid = (priceDiffFromLast >= PyramidInterval);
    }
    else if(PyramidMode == 1) // 逆势补仓模式
    {
        // 逆势补仓:当空单亏损达到间隔时补仓
        double currentProfitPoints = (avgSellPrice - currentPrice) / Point;
        shouldPyramid = (currentProfitPoints <= -PyramidInterval);
    }

    if(shouldPyramid)
    {
        double pyramidLot = CalculatePyramidLot(OP_SELL);
        if(pyramidLot > 0)
        {
            OpenSellOrder(pyramidLot);
            string modeStr = (PyramidMode == 0) ? "顺势加仓" : "逆势补仓";
            Print("空单", modeStr, " #", sellCount + 1, " 手数:", pyramidLot);
        }
    }
}

//+------------------------------------------------------------------+
//| 计算加仓手数                                                     |
//+------------------------------------------------------------------+
double CalculatePyramidLot(int orderType)
{
    int orderCount = CountOrders(orderType);

    if(orderCount >= MaxPyramidLevel)
        return 0;

    double pyramidLot = FirstLotSize * MathPow(PyramidMultiplier, orderCount);
    pyramidLot = NormalizeLot(pyramidLot);

    return pyramidLot;
}

//+------------------------------------------------------------------+
//| 获取平均开仓价格                                                 |
//+------------------------------------------------------------------+
double GetAveragePrice(int orderType)
{
    double totalLots = 0;
    double totalValue = 0;

    for(int i = 0; i < OrdersTotal(); i++)
    {
        if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
        {
            if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && OrderType() == orderType)
            {
                totalValue += OrderOpenPrice() * OrderLots();
                totalLots += OrderLots();
            }
        }
    }

    return (totalLots > 0) ? totalValue / totalLots : 0;
}

//+------------------------------------------------------------------+
//| 标准化手数                                                       |
//+------------------------------------------------------------------+
double NormalizeLot(double lot)
{
    double minlot = MarketInfo(Symbol(), MODE_MINLOT);
    double maxlot = MarketInfo(Symbol(), MODE_MAXLOT);
    double steplot = MarketInfo(Symbol(), MODE_LOTSTEP);

    if(lot < minlot) lot = minlot;
    if(lot > maxlot) lot = maxlot;

    lot = MathRound(lot / steplot) * steplot;

    return NormalizeDouble(lot, 2);
}

//+------------------------------------------------------------------+
//| 统计订单数量                                                     |
//+------------------------------------------------------------------+
int CountOrders(int orderType = -1)
{
    int count = 0;
    for(int i = 0; i < OrdersTotal(); i++)
    {
        if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
        {
            if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
            {
                if(orderType == -1)
                    count++;
                else if(OrderType() == orderType)
                    count++;
            }
        }
    }
    return count;
}

//+------------------------------------------------------------------+
//| 获取最后订单价格                                                 |
//+------------------------------------------------------------------+
double GetLastOrderPrice(int orderType)
{
    datetime lastTime = 0;
    double lastPrice = 0;

    for(int i = 0; i < OrdersTotal(); i++)
    {
        if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
        {
            if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && OrderType() == orderType)
            {
                if(OrderOpenTime() > lastTime)
                {
                    lastTime = OrderOpenTime();
                    lastPrice = OrderOpenPrice();
                }
            }
        }
    }

    return lastPrice;
}

//+------------------------------------------------------------------+
//| 开多单                                                           |
//+------------------------------------------------------------------+
void OpenBuyOrder(double lotSize)
{
    if(lotSize <= 0) return;

    double price = Ask;
    int ticket = OrderSend(Symbol(), OP_BUY, lotSize, price, 3, 0, 0,
                         "GoldenCross Buy", MagicNumber, 0, Green);

    if(ticket > 0)
    {
        Print("多单开仓成功: 订单=", ticket, " 手数=", lotSize, " 价格=", price);
        lastTradeTime = TimeCurrent();
    }
    else
    {
        Print("多单开仓失败: 错误=", GetLastError());
    }
}

//+------------------------------------------------------------------+
//| 开空单                                                           |
//+------------------------------------------------------------------+
void OpenSellOrder(double lotSize)
{
    if(lotSize <= 0) return;

    double price = Bid;
    int ticket = OrderSend(Symbol(), OP_SELL, lotSize, price, 3, 0, 0,
                         "GoldenCross Sell", MagicNumber, 0, Red);

    if(ticket > 0)
    {
        Print("空单开仓成功: 订单=", ticket, " 手数=", lotSize, " 价格=", price);
        lastTradeTime = TimeCurrent();
    }
    else
    {
        Print("空单开仓失败: 错误=", GetLastError());
    }
}

//+------------------------------------------------------------------+
//| 平仓所有订单                                                     |
//+------------------------------------------------------------------+
void CloseAllOrders()
{
    for(int i = OrdersTotal() - 1; i >= 0; i--)
    {
        if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
        {
            if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
            {
                double closePrice = (OrderType() == OP_BUY) ? Bid : Ask;
                bool result = OrderClose(OrderTicket(), OrderLots(), closePrice, 3, Yellow);
                if(result)
                    Print("订单平仓成功: ", OrderTicket());
                else
                    Print("订单平仓失败: ", GetLastError());
            }
        }
    }
}

//+------------------------------------------------------------------+
//| 平仓指定类型的所有订单                                           |
//+------------------------------------------------------------------+
void CloseAllOrdersByType(int orderType)
{
    for(int i = OrdersTotal() - 1; i >= 0; i--)
    {
        if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
        {
            if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber && OrderType() == orderType)
            {
                double closePrice = (orderType == OP_BUY) ? Bid : Ask;
                bool result = OrderClose(OrderTicket(), OrderLots(), closePrice, 3, Yellow);
                if(result)
                    Print("订单平仓成功: ", OrderTicket());
                else
                    Print("订单平仓失败: ", GetLastError());
            }
        }
    }
}

//+------------------------------------------------------------------+
//| 更新移动平均线数据                                               |
//+------------------------------------------------------------------+
bool UpdateMAData()
{
    fastMA0 = iMA(NULL, 0, FastMAPeriod, 0, MODE_EMA, PRICE_CLOSE, 0);
    fastMA1 = iMA(NULL, 0, FastMAPeriod, 0, MODE_EMA, PRICE_CLOSE, 1);
    slowMA0 = iMA(NULL, 0, SlowMAPeriod, 0, MODE_EMA, PRICE_CLOSE, 0);
    slowMA1 = iMA(NULL, 0, SlowMAPeriod, 0, MODE_EMA, PRICE_CLOSE, 1);

    return (fastMA0 != 0 && slowMA0 != 0);
}
//+------------------------------------------------------------------+

logo

最近访问 头像模式
举报

评论 使用道具

发新帖
EA交易
您需要登录后才可以评论 登录 | 立即注册

 简体中文国旗 简体中文
 繁體中文国旗 繁體中文
 English国旗 English(英语)
 日本語国旗 日本語(日语)
 Deutsch国旗 Deutsch(德语)
 Русский язык国旗 Русский язык(俄语)
 بالعربية国旗 بالعربية(阿拉伯语)
 Türkçe国旗 Türkçe(土耳其语)
 Português国旗 Português(葡萄牙语)
 ภาษาไทย国旗 ภาษาไทย(泰国语)
 한어国旗 한어(朝鲜语/韩语)
 Français国旗 Français(法语)
翻译