henry的动态网格策略,NVDA跑今年的数据,日线,模拟盘1万本金,160%收益  热门

| 发表于 2025-8-23 15:49:28 | 显示全部楼层 |复制链接
image.png

image.png
NVDA跑今年的数据,日线,模拟盘1万本金,160%收益
  1. #property description "动态网格策略 - Dynamic Grid Trading Strategy"
  2. #include <Trade\Trade.mqh>
  3. //--- 输入参数
  4. input group "=== 基础参数 ==="
  5. input double   InpLotSize = 0.0001;        // 基础手数
  6. input int      InpMagicNumber = 12349;     // 魔术数字
  7. input double   InpTotalRisk = 0.05;        // 总风险比例
  8. input group "=== 动态网格参数 ==="
  9. input int      InpBaseGridStep = 200;      // 基础网格间距(点)
  10. input int      InpMaxGridLevels = 2;       // 最大网格层数
  11. input double   InpATRMultiplier = 1.5;     // ATR倍数
  12. input int      InpATRPeriod = 14;          // ATR周期
  13. input bool     InpUseATRSpacing = false;   // 使用ATR动态间距
  14. input group "=== 网格管理 ==="
  15. input double   InpGridVolumeMultiplier = 1.0; // 网格手数倍数
  16. input bool     InpUseMartingale = false;   // 使用马丁格尔
  17. input double   InpMartingaleMultiplier = 2.0; // 马丁格尔倍数
  18. input int      InpMaxPositions = 5;        // 最大持仓数量
  19. input group "=== 市场条件 ==="
  20. input bool     InpUseVolatilityFilter = true; // 使用波动率过滤
  21. input double   InpMinVolatility = 0.0001;  // 最小波动率
  22. input double   InpMaxVolatility = 0.005;   // 最大波动率
  23. input bool     InpUseTrendFilter = false;  // 使用趋势过滤
  24. input int      InpTrendPeriod = 50;        // 趋势判断周期
  25. input group "=== 动态调整 ==="
  26. input bool     InpDynamicLotSize = true;   // 动态手数调整
  27. input bool     InpDynamicSpacing = false;  // 动态间距调整
  28. input int      InpVolatilityCheckPeriod = 100; // 波动率检查周期
  29. input double   InpVolatilityThreshold = 1.5; // 波动率变化阈值
  30. input group "=== 风险控制 ==="
  31. input double   InpMaxDrawdown = 0.01;      // 最大回撤比例
  32. input double   InpDailyLossLimit = 0.005;  // 日损失限制
  33. input bool     InpUseEquityStop = true;    // 使用净值止损
  34. input double   InpEquityStopPercent = 0.15; // 净值止损百分比
  35. //--- 全局变量
  36. CTrade         g_trade;                    // 交易对象
  37. double         g_point_value;              // 点值
  38. datetime       g_last_grid_update;         // 上次网格更新时间
  39. double         g_account_start_balance;    // 账户起始余额
  40. double         g_daily_start_balance;      // 日起始余额
  41. datetime       g_daily_reset_time;         // 日重置时间
  42. //--- 动态网格策略特定变量
  43. int            g_atr_handle;               // ATR句柄
  44. int            g_trend_ma_handle;          // 趋势MA句柄
  45. double         g_atr_values[];             // ATR值缓冲区
  46. double         g_trend_ma[];               // 趋势MA缓冲区
  47. // 网格状态结构
  48. struct GridLevel
  49. {
  50.     double   price;         // 网格价格
  51.     ulong    buy_ticket;    // 买单票据
  52.     ulong    sell_ticket;   // 卖单票据
  53.     double   lot_size;      // 手数
  54.     datetime create_time;   // 创建时间
  55.     bool     is_active;     // 是否激活
  56. };
  57. GridLevel      g_grid_levels[];            // 网格层级数组
  58. double         g_current_grid_spacing;     // 当前网格间距
  59. double         g_base_price;               // 网格基准价格
  60. bool           g_grid_active;              // 网格是否激活
  61. int            g_active_grid_count;        // 激活的网格数量
  62. //--- 市场状态枚举
  63. enum ENUM_MARKET_STATE
  64. {
  65.     MARKET_RANGING,     // 震荡市
  66.     MARKET_TRENDING_UP, // 上升趋势
  67.     MARKET_TRENDING_DOWN, // 下降趋势
  68.     MARKET_HIGH_VOLATILITY, // 高波动
  69.     MARKET_LOW_VOLATILITY   // 低波动
  70. };
  71. ENUM_MARKET_STATE g_market_state = MARKET_RANGING;
  72. //+------------------------------------------------------------------+
  73. //| Expert initialization function                                   |
  74. //+------------------------------------------------------------------+
  75. int OnInit()
  76. {
  77.     // 基础初始化
  78.     if(!BaseInitialization())
  79.         return INIT_FAILED;
  80.     // 策略特定初始化
  81.     if(!StrategyInitialization())
  82.         return INIT_FAILED;
  83.     Print("动态网格策略初始化成功: ", _Symbol);
  84.     return INIT_SUCCEEDED;
  85. }
  86. //+------------------------------------------------------------------+
  87. //| Expert deinitialization function                                 |
  88. //+------------------------------------------------------------------+
  89. void OnDeinit(const int reason)
  90. {
  91.     // 策略特定清理
  92.     StrategyDeinitialization();
  93.     // 基础清理
  94.     BaseDeinitialization();
  95.     Print("动态网格策略已停止运行");
  96. }
  97. //+------------------------------------------------------------------+
  98. //| Expert tick function                                             |
  99. //+------------------------------------------------------------------+
  100. void OnTick()
  101. {
  102.     // 基础检查
  103.     if(!BaseChecks())
  104.         return;
  105.     // 更新市场状态
  106.     UpdateMarketState();
  107.     // 检查风险控制
  108.     if(!CheckRiskLimits())
  109.     {
  110.         if(g_grid_active)
  111.         {
  112.             Print("触发风险限制,暂停网格交易");
  113.             g_grid_active = false;
  114.         }
  115.         return;
  116.     }
  117.     // 动态调整网格参数
  118.     if(TimeCurrent() - g_last_grid_update >= InpVolatilityCheckPeriod)
  119.     {
  120.         UpdateDynamicParameters();
  121.         g_last_grid_update = TimeCurrent();
  122.     }
  123.     // 网格管理
  124.     ManageGrid();
  125.     // 管理现有持仓
  126.     ManagePositions();
  127. }
  128. //+------------------------------------------------------------------+
  129. //| 基础初始化                                                        |
  130. //+------------------------------------------------------------------+
  131. bool BaseInitialization()
  132. {
  133.     // 获取点值
  134.     g_point_value = _Point;
  135.     if(_Digits == 5 || _Digits == 3)
  136.         g_point_value = _Point * 10;
  137.     // 初始化账户信息
  138.     g_account_start_balance = AccountInfoDouble(ACCOUNT_BALANCE);
  139.     g_daily_start_balance = AccountInfoDouble(ACCOUNT_BALANCE);
  140.     g_daily_reset_time = TimeCurrent() - (TimeCurrent() % 86400); // 当日0点
  141.     // 初始化CTrade对象
  142.     g_trade.SetExpertMagicNumber(InpMagicNumber);
  143.     g_trade.SetMarginMode();
  144.     g_trade.SetTypeFillingBySymbol(_Symbol);
  145.     g_trade.SetDeviationInPoints(10);
  146.     // 验证输入参数
  147.     if(InpLotSize <= 0)
  148.     {
  149.         Print("错误: 手数必须大于0");
  150.         return false;
  151.     }
  152.     if(InpMagicNumber <= 0)
  153.     {
  154.         Print("错误: 魔术数字必须大于0");
  155.         return false;
  156.     }
  157.     if(InpMaxGridLevels <= 0 || InpMaxGridLevels > 50)
  158.     {
  159.         Print("错误: 最大网格层数必须在1-50之间");
  160.         return false;
  161.     }
  162.     // 初始化网格变量
  163.     g_current_grid_spacing = InpBaseGridStep * g_point_value;
  164.     g_base_price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
  165.     g_grid_active = true;
  166.     g_active_grid_count = 0;
  167.     g_last_grid_update = TimeCurrent();
  168.     return true;
  169. }
  170. //+------------------------------------------------------------------+
  171. //| 动态网格策略初始化                                                 |
  172. //+------------------------------------------------------------------+
  173. bool StrategyInitialization()
  174. {
  175.     // 创建ATR指标句柄
  176.     if(InpUseATRSpacing)
  177.     {
  178.         g_atr_handle = iATR(_Symbol, PERIOD_CURRENT, InpATRPeriod);
  179.         if(g_atr_handle == INVALID_HANDLE)
  180.         {
  181.             Print("创建ATR指标失败");
  182.             return false;
  183.         }
  184.     }
  185.     // 创建趋势MA句柄
  186.     if(InpUseTrendFilter)
  187.     {
  188.         g_trend_ma_handle = iMA(_Symbol, PERIOD_CURRENT,
  189.                                InpTrendPeriod, 0, MODE_EMA, PRICE_CLOSE);
  190.         if(g_trend_ma_handle == INVALID_HANDLE)
  191.         {
  192.             Print("创建趋势MA指标失败");
  193.             return false;
  194.         }
  195.     }
  196.     // 设置缓冲区为时间序列
  197.     ArraySetAsSeries(g_atr_values, true);
  198.     ArraySetAsSeries(g_trend_ma, true);
  199.     // 初始化网格数组
  200.     ArrayResize(g_grid_levels, InpMaxGridLevels * 2); // 买卖各一半
  201.     for(int i = 0; i < ArraySize(g_grid_levels); i++)
  202.     {
  203.         g_grid_levels.price = 0;
  204.         g_grid_levels.buy_ticket = 0;
  205.         g_grid_levels.sell_ticket = 0;
  206.         g_grid_levels.lot_size = InpLotSize;
  207.         g_grid_levels.create_time = 0;
  208.         g_grid_levels.is_active = false;
  209.     }
  210.     // 验证参数
  211.     if(InpATRMultiplier <= 0 || InpATRMultiplier > 10)
  212.     {
  213.         Print("错误: ATR倍数必须在0-10之间");
  214.         return false;
  215.     }
  216.     if(InpGridVolumeMultiplier < 1.0 || InpGridVolumeMultiplier > 5.0)
  217.     {
  218.         Print("错误: 网格手数倍数必须在1.0-5.0之间");
  219.         return false;
  220.     }
  221.     if(InpMaxDrawdown <= 0 || InpMaxDrawdown > 1.0)
  222.     {
  223.         Print("错误: 最大回撤比例必须在0-1之间");
  224.         return false;
  225.     }
  226.     Print("动态网格策略初始化成功");
  227.     Print("基础网格间距: ", InpBaseGridStep, "点");
  228.     Print("最大网格层数: ", InpMaxGridLevels);
  229.     Print("ATR动态间距: ", InpUseATRSpacing ? "启用" : "禁用");
  230.     Print("波动率过滤: ", InpUseVolatilityFilter ? "启用" : "禁用");
  231.     Print("趋势过滤: ", InpUseTrendFilter ? "启用" : "禁用");
  232.     return true;
  233. }
  234. //+------------------------------------------------------------------+
  235. //| 基础清理                                                          |
  236. //+------------------------------------------------------------------+
  237. void BaseDeinitialization()
  238. {
  239.     // 基础清理工作
  240. }
  241. //+------------------------------------------------------------------+
  242. //| 动态网格策略清理                                                   |
  243. //+------------------------------------------------------------------+
  244. void StrategyDeinitialization()
  245. {
  246.     // 释放ATR指标句柄
  247.     if(InpUseATRSpacing && g_atr_handle != INVALID_HANDLE)
  248.     {
  249.         IndicatorRelease(g_atr_handle);
  250.         Print("ATR指标句柄已释放");
  251.     }
  252.     // 释放趋势MA句柄
  253.     if(InpUseTrendFilter && g_trend_ma_handle != INVALID_HANDLE)
  254.     {
  255.         IndicatorRelease(g_trend_ma_handle);
  256.         Print("趋势MA指标句柄已释放");
  257.     }
  258. }
  259. //+------------------------------------------------------------------+
  260. //| 基础检查                                                          |
  261. //+------------------------------------------------------------------+
  262. bool BaseChecks()
  263. {
  264.     // 检查市场状态
  265.     if(!IsMarketOpen())
  266.         return false;
  267.     return true;
  268. }
  269. //+------------------------------------------------------------------+
  270. //| 检查市场是否开放                                                   |
  271. //+------------------------------------------------------------------+
  272. bool IsMarketOpen()
  273. {
  274.     MqlTick tick;
  275.     if(!SymbolInfoTick(_Symbol, tick))
  276.         return false;
  277.     return tick.time > 0;
  278. }
  279. //+------------------------------------------------------------------+
  280. //| 更新市场状态                                                       |
  281. //+------------------------------------------------------------------+
  282. void UpdateMarketState()
  283. {
  284.     double current_price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
  285.     // 获取ATR值用于波动率判断
  286.     if(InpUseATRSpacing && CopyBuffer(g_atr_handle, 0, 0, 5, g_atr_values) >= 5)
  287.     {
  288.         double current_atr = g_atr_values[0];
  289.         double avg_atr = (g_atr_values[0] + g_atr_values[1] + g_atr_values[2] +
  290.                          g_atr_values[3] + g_atr_values[4]) / 5.0;
  291.         // 判断波动率状态
  292.         if(current_atr > avg_atr * InpVolatilityThreshold)
  293.         {
  294.             g_market_state = MARKET_HIGH_VOLATILITY;
  295.         }
  296.         else if(current_atr < avg_atr / InpVolatilityThreshold)
  297.         {
  298.             g_market_state = MARKET_LOW_VOLATILITY;
  299.         }
  300.     }
  301.     // 获取趋势状态 - 增强趋势识别
  302.     if(InpUseTrendFilter && CopyBuffer(g_trend_ma_handle, 0, 0, 10, g_trend_ma) >= 10)
  303.     {
  304.         double price_vs_ma = (current_price - g_trend_ma[0]) / g_trend_ma[0];
  305.         double ma_trend = (g_trend_ma[0] - g_trend_ma[9]) / g_trend_ma[9];
  306.         // 更严格的趋势判断
  307.         if(price_vs_ma > 0.01 && ma_trend > 0.005) // 价格高于MA 1%且MA上升0.5%
  308.         {
  309.             if(g_market_state != MARKET_HIGH_VOLATILITY && g_market_state != MARKET_LOW_VOLATILITY)
  310.                 g_market_state = MARKET_TRENDING_UP;
  311.         }
  312.         else if(price_vs_ma < -0.01 && ma_trend < -0.005) // 价格低于MA 1%且MA下降0.5%
  313.         {
  314.             if(g_market_state != MARKET_HIGH_VOLATILITY && g_market_state != MARKET_LOW_VOLATILITY)
  315.                 g_market_state = MARKET_TRENDING_DOWN;
  316.         }
  317.         else
  318.         {
  319.             if(g_market_state != MARKET_HIGH_VOLATILITY && g_market_state != MARKET_LOW_VOLATILITY)
  320.                 g_market_state = MARKET_RANGING;
  321.         }
  322.     }
  323. }
  324. //+------------------------------------------------------------------+
  325. //| 检查风险限制                                                       |
  326. //+------------------------------------------------------------------+
  327. bool CheckRiskLimits()
  328. {
  329.     double current_balance = AccountInfoDouble(ACCOUNT_BALANCE);
  330.     double current_equity = AccountInfoDouble(ACCOUNT_EQUITY);
  331.     // 检查日损失限制
  332.     datetime current_day = TimeCurrent() - (TimeCurrent() % 86400);
  333.     if(current_day != g_daily_reset_time)
  334.     {
  335.         g_daily_reset_time = current_day;
  336.         g_daily_start_balance = current_balance;
  337.     }
  338.     double daily_loss = (g_daily_start_balance - current_balance) / g_daily_start_balance;
  339.     if(daily_loss > InpDailyLossLimit)
  340.     {
  341.         Print("达到日损失限制: ", DoubleToString(daily_loss * 100, 2), "%");
  342.         return false;
  343.     }
  344.     // 检查最大回撤
  345.     double drawdown = (g_account_start_balance - current_balance) / g_account_start_balance;
  346.     if(drawdown > InpMaxDrawdown)
  347.     {
  348.         Print("达到最大回撤限制: ", DoubleToString(drawdown * 100, 2), "%");
  349.         return false;
  350.     }
  351.     // 检查净值止损
  352.     if(InpUseEquityStop)
  353.     {
  354.         double equity_loss = (current_balance - current_equity) / current_balance;
  355.         if(equity_loss > InpEquityStopPercent)
  356.         {
  357.             Print("触发净值止损: ", DoubleToString(equity_loss * 100, 2), "%");
  358.             return false;
  359.         }
  360.     }
  361.     return true;
  362. }
  363. //+------------------------------------------------------------------+
  364. //| 更新动态参数                                                       |
  365. //+------------------------------------------------------------------+
  366. void UpdateDynamicParameters()
  367. {
  368.     // 禁用动态间距调整,使用固定间距
  369.     /*
  370.     // 动态间距调整
  371.     if(InpDynamicSpacing && InpUseATRSpacing)
  372.     {
  373.         if(CopyBuffer(g_atr_handle, 0, 0, 1, g_atr_values) >= 1)
  374.         {
  375.             double new_spacing = g_atr_values[0] * InpATRMultiplier;
  376.             // 限制间距在合理范围内
  377.             double min_spacing = InpBaseGridStep * g_point_value * 0.5;
  378.             double max_spacing = InpBaseGridStep * g_point_value * 3.0;
  379.             new_spacing = MathMax(min_spacing, MathMin(max_spacing, new_spacing));
  380.             if(MathAbs(new_spacing - g_current_grid_spacing) / g_current_grid_spacing > 0.5)
  381.             {
  382.                 g_current_grid_spacing = new_spacing;
  383.                 Print("动态调整网格间距: ", DoubleToString(g_current_grid_spacing / g_point_value, 1), "点");
  384.                 // 减少频繁重新计算,避免过多canceled订单
  385.                 // RecalculateGridLevels();
  386.             }
  387.         }
  388.     }
  389.     */
  390.     // 动态手数调整
  391.     if(InpDynamicLotSize)
  392.     {
  393.         UpdateDynamicLotSizes();
  394.     }
  395. }
  396. //+------------------------------------------------------------------+
  397. //| 重新计算网格层级                                                   |
  398. //+------------------------------------------------------------------+
  399. void RecalculateGridLevels()
  400. {
  401.     double current_price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
  402.     g_base_price = current_price;
  403.     // 重新计算所有网格价格
  404.     for(int i = 0; i < ArraySize(g_grid_levels); i++)
  405.     {
  406.         if(g_grid_levels.is_active)
  407.         {
  408.             // 暂时禁用旧网格,等待新价格计算
  409.             g_grid_levels.is_active = false;
  410.         }
  411.     }
  412.     // 根据新间距重新设置网格
  413.     SetupInitialGrid();
  414. }
  415. //+------------------------------------------------------------------+
  416. //| 更新动态手数                                                       |
  417. //+------------------------------------------------------------------+
  418. void UpdateDynamicLotSizes()
  419. {
  420.     double account_balance = AccountInfoDouble(ACCOUNT_BALANCE);
  421.     double risk_amount = account_balance * InpTotalRisk;
  422.     // 根据当前激活的网格数量调整手数
  423.     int active_grids = CountActiveGrids();
  424.     if(active_grids > 0)
  425.     {
  426.         double new_lot_size = risk_amount / (active_grids * 1000 * g_current_grid_spacing / g_point_value);
  427.         new_lot_size = NormalizeLotSize(new_lot_size);
  428.         // 更新未激活网格的手数
  429.         for(int i = 0; i < ArraySize(g_grid_levels); i++)
  430.         {
  431.             if(!g_grid_levels.is_active)
  432.             {
  433.                 g_grid_levels.lot_size = new_lot_size;
  434.             }
  435.         }
  436.     }
  437. }
  438. //+------------------------------------------------------------------+
  439. //| 网格管理                                                           |
  440. //+------------------------------------------------------------------+
  441. void ManageGrid()
  442. {
  443.     if(!g_grid_active)
  444.         return;
  445.     // 检查是否需要初始化网格
  446.     if(g_active_grid_count == 0)
  447.     {
  448.         SetupInitialGrid();
  449.     }
  450.     // 检查网格触发
  451.     CheckGridTriggers();
  452.     // 清理已完成的网格订单
  453.     CleanupCompletedGrids();
  454. }
  455. //+------------------------------------------------------------------+
  456. //| 设置初始网格                                                       |
  457. //+------------------------------------------------------------------+
  458. void SetupInitialGrid()
  459. {
  460.     double current_price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
  461.     g_base_price = current_price;
  462.     // 根据市场状态调整网格设置
  463.     int buy_levels = InpMaxGridLevels / 2;
  464.     int sell_levels = InpMaxGridLevels / 2;
  465.     switch(g_market_state)
  466.     {
  467.         case MARKET_TRENDING_UP:
  468.             // 上涨趋势只做买入网格,禁止卖出
  469.             buy_levels = InpMaxGridLevels;
  470.             sell_levels = 0;
  471.             break;
  472.         case MARKET_TRENDING_DOWN:
  473.             // 下跌趋势只做卖出网格,禁止买入
  474.             buy_levels = 0;
  475.             sell_levels = InpMaxGridLevels;
  476.             break;
  477.         case MARKET_HIGH_VOLATILITY:
  478.         case MARKET_LOW_VOLATILITY:
  479.             // 高波动和低波动时都暂停网格交易
  480.             buy_levels = 0;
  481.             sell_levels = 0;
  482.             g_grid_active = false;
  483.             Print("波动异常市场,暂停网格交易");
  484.             return;
  485.         default:
  486.             // 震荡市允许双向网格
  487.             buy_levels = InpMaxGridLevels / 2;
  488.             sell_levels = InpMaxGridLevels / 2;
  489.             if(buy_levels == 0) buy_levels = 1;
  490.             if(sell_levels == 0) sell_levels = 1;
  491.             break;
  492.     }
  493.     // 设置买入网格
  494.     for(int i = 0; i < buy_levels; i++)
  495.     {
  496.         double grid_price = current_price - (i + 1) * g_current_grid_spacing;
  497.         SetupGridLevel(i, grid_price, ORDER_TYPE_BUY_LIMIT);
  498.     }
  499.     // 设置卖出网格
  500.     for(int i = 0; i < sell_levels; i++)
  501.     {
  502.         double grid_price = current_price + (i + 1) * g_current_grid_spacing;
  503.         SetupGridLevel(buy_levels + i, grid_price, ORDER_TYPE_SELL_LIMIT);
  504.     }
  505.     Print("初始网格设置完成 - 买入层级: ", buy_levels, " 卖出层级: ", sell_levels);
  506. }
  507. //+------------------------------------------------------------------+
  508. //| 设置网格层级                                                       |
  509. //+------------------------------------------------------------------+
  510. void SetupGridLevel(int index, double price, ENUM_ORDER_TYPE order_type)
  511. {
  512.     if(index >= ArraySize(g_grid_levels))
  513.         return;
  514.     double lot_size = CalculateGridLotSize(index);
  515.     lot_size = NormalizeLotSize(lot_size);
  516.     string comment = StringFormat("Grid_%d_%s", index, order_type == ORDER_TYPE_BUY_LIMIT ? "BUY" : "SELL");
  517.     bool trade_result = false;
  518.     if(order_type == ORDER_TYPE_BUY_LIMIT)
  519.     {
  520.         trade_result = g_trade.BuyLimit(lot_size, price, _Symbol, 0, 0, ORDER_TIME_GTC, 0, comment);
  521.     }
  522.     else if(order_type == ORDER_TYPE_SELL_LIMIT)
  523.     {
  524.         trade_result = g_trade.SellLimit(lot_size, price, _Symbol, 0, 0, ORDER_TIME_GTC, 0, comment);
  525.     }
  526.     if(trade_result)
  527.     {
  528.         ulong ticket = g_trade.ResultOrder();
  529.         if(ticket > 0)
  530.         {
  531.             g_grid_levels[index].price = price;
  532.             g_grid_levels[index].lot_size = lot_size;
  533.             g_grid_levels[index].create_time = TimeCurrent();
  534.             g_grid_levels[index].is_active = true;
  535.             if(order_type == ORDER_TYPE_BUY_LIMIT)
  536.                 g_grid_levels[index].buy_ticket = ticket;
  537.             else
  538.                 g_grid_levels[index].sell_ticket = ticket;
  539.             g_active_grid_count++;
  540.         }
  541.     }
  542.     else
  543.     {
  544.         Print("网格订单创建失败: ", g_trade.ResultRetcode(), " - ", g_trade.ResultComment());
  545.     }
  546. }
  547. //+------------------------------------------------------------------+
  548. //| 计算网格手数                                                       |
  549. //+------------------------------------------------------------------+
  550. double CalculateGridLotSize(int level)
  551. {
  552.     // 固定手数,不再递增
  553.     double base_lot = InpLotSize;
  554.     // 禁用马丁格尔和手数递增,避免快速亏损
  555.     /*
  556.     if(InpUseMartingale)
  557.     {
  558.         // 马丁格尔递增
  559.         base_lot = InpLotSize * MathPow(InpMartingaleMultiplier, level / 2);
  560.     }
  561.     else
  562.     {
  563.         // 普通递增
  564.         base_lot = InpLotSize * MathPow(InpGridVolumeMultiplier, level / 2);
  565.     }
  566.     */
  567.     return NormalizeLotSize(base_lot);
  568. }
  569. //+------------------------------------------------------------------+
  570. //| 标准化手数                                                         |
  571. //+------------------------------------------------------------------+
  572. double NormalizeLotSize(double volume)
  573. {
  574.     double min_vol = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
  575.     double max_vol = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
  576.     double vol_step = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
  577.     // 检查保证金需求,确保账户有足够资金
  578.     double margin_required = 0;
  579.     if(!OrderCalcMargin(ORDER_TYPE_BUY, _Symbol, volume, SymbolInfoDouble(_Symbol, SYMBOL_ASK), margin_required))
  580.     {
  581.         Print("无法计算保证金需求");
  582.         return 0;
  583.     }
  584.     double free_margin = AccountInfoDouble(ACCOUNT_FREEMARGIN);
  585.     if(margin_required > free_margin * 0.1) // 保留90%安全边际,极度保守
  586.     {
  587.         volume = volume * (free_margin * 0.1) / margin_required;
  588.         Print("调整手数以适应保证金: ", volume);
  589.     }
  590.     // 外汇杠杆风险控制:限制单笔交易最大手数
  591.     double max_single_lot = AccountInfoDouble(ACCOUNT_BALANCE) / 100000.0; // 每10万余额限制1手
  592.     if(volume > max_single_lot)
  593.     {
  594.         volume = max_single_lot;
  595.         Print("限制最大手数防止杠杆风险: ", volume);
  596.     }
  597.     // 确保音量符合要求
  598.     volume = MathMax(volume, min_vol);
  599.     volume = MathMin(volume, max_vol);
  600.     volume = MathRound(volume / vol_step) * vol_step;
  601.     Print("交易量信息: 输入=", volume, " 最小=", min_vol, " 最大=", max_vol, " 步长=", vol_step, " 最终=", volume);
  602.     Print("保证金需求: ", margin_required, " 自由保证金: ", free_margin);
  603.     return volume;
  604. }
  605. //+------------------------------------------------------------------+
  606. //| 检查网格触发                                                       |
  607. //+------------------------------------------------------------------+
  608. void CheckGridTriggers()
  609. {
  610.     double current_price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
  611.     for(int i = 0; i < ArraySize(g_grid_levels); i++)
  612.     {
  613.         if(!g_grid_levels.is_active)
  614.             continue;
  615.         // 检查订单是否已执行
  616.         if(g_grid_levels.buy_ticket > 0)
  617.         {
  618.             if(!OrderSelect(g_grid_levels.buy_ticket))
  619.             {
  620.                 // 买单已执行,设置对应的卖出订单
  621.                 SetupCounterOrder(i, ORDER_TYPE_SELL_LIMIT);
  622.                 g_grid_levels.buy_ticket = 0;
  623.             }
  624.         }
  625.         if(g_grid_levels.sell_ticket > 0)
  626.         {
  627.             if(!OrderSelect(g_grid_levels.sell_ticket))
  628.             {
  629.                 // 卖单已执行,设置对应的买入订单
  630.                 SetupCounterOrder(i, ORDER_TYPE_BUY_LIMIT);
  631.                 g_grid_levels.sell_ticket = 0;
  632.             }
  633.         }
  634.     }
  635. }
  636. //+------------------------------------------------------------------+
  637. //| 设置反向订单                                                       |
  638. //+------------------------------------------------------------------+
  639. void SetupCounterOrder(int grid_index, ENUM_ORDER_TYPE order_type)
  640. {
  641.     double grid_price = g_grid_levels[grid_index].price;
  642.     double counter_price;
  643.     if(order_type == ORDER_TYPE_BUY_LIMIT)
  644.     {
  645.         counter_price = grid_price - g_current_grid_spacing;
  646.     }
  647.     else
  648.     {
  649.         counter_price = grid_price + g_current_grid_spacing;
  650.     }
  651.     // 寻找空闲的网格位置
  652.     int free_index = FindFreeGridIndex();
  653.     if(free_index >= 0)
  654.     {
  655.         SetupGridLevel(free_index, counter_price, order_type);
  656.     }
  657. }
  658. //+------------------------------------------------------------------+
  659. //| 查找空闲网格索引                                                   |
  660. //+------------------------------------------------------------------+
  661. int FindFreeGridIndex()
  662. {
  663.     for(int i = 0; i < ArraySize(g_grid_levels); i++)
  664.     {
  665.         if(!g_grid_levels.is_active)
  666.             return i;
  667.     }
  668.     return -1;
  669. }
  670. //+------------------------------------------------------------------+
  671. //| 清理已完成的网格                                                   |
  672. //+------------------------------------------------------------------+
  673. void CleanupCompletedGrids()
  674. {
  675.     for(int i = 0; i < ArraySize(g_grid_levels); i++)
  676.     {
  677.         if(!g_grid_levels.is_active)
  678.             continue;
  679.         bool should_remove = false;
  680.         // 检查订单是否已被取消或过期
  681.         if(g_grid_levels.buy_ticket > 0)
  682.         {
  683.             if(!OrderSelect(g_grid_levels.buy_ticket))
  684.                 should_remove = true;
  685.         }
  686.         if(g_grid_levels.sell_ticket > 0)
  687.         {
  688.             if(!OrderSelect(g_grid_levels.sell_ticket))
  689.                 should_remove = true;
  690.         }
  691.         if(should_remove)
  692.         {
  693.             g_grid_levels.is_active = false;
  694.             g_grid_levels.buy_ticket = 0;
  695.             g_grid_levels.sell_ticket = 0;
  696.             g_active_grid_count--;
  697.         }
  698.     }
  699. }
  700. //+------------------------------------------------------------------+
  701. //| 统计激活网格数量                                                   |
  702. //+------------------------------------------------------------------+
  703. int CountActiveGrids()
  704. {
  705.     int count = 0;
  706.     for(int i = 0; i < ArraySize(g_grid_levels); i++)
  707.     {
  708.         if(g_grid_levels.is_active)
  709.             count++;
  710.     }
  711.     return count;
  712. }
  713. //+------------------------------------------------------------------+
  714. //| 持仓管理                                                           |
  715. //+------------------------------------------------------------------+
  716. void ManagePositions()
  717. {
  718.     // 检查持仓数量限制
  719.     int total_positions = CountPositions();
  720.     if(total_positions >= InpMaxPositions)
  721.     {
  722.         Print("达到最大持仓数量限制: ", total_positions);
  723.         g_grid_active = false;
  724.         return;
  725.     }
  726.     // 检查是否需要重新激活网格
  727.     if(!g_grid_active && total_positions < InpMaxPositions / 2)
  728.     {
  729.         if(CheckRiskLimits())
  730.         {
  731.             g_grid_active = true;
  732.             Print("重新激活网格交易");
  733.         }
  734.     }
  735. }
  736. //+------------------------------------------------------------------+
  737. //| 统计持仓数量                                                       |
  738. //+------------------------------------------------------------------+
  739. int CountPositions()
  740. {
  741.     int count = 0;
  742.     for(int i = 0; i < PositionsTotal(); i++)
  743.     {
  744.         if(PositionGetTicket(i))
  745.         {
  746.             if(PositionGetString(POSITION_SYMBOL) == _Symbol &&
  747.                PositionGetInteger(POSITION_MAGIC) == InpMagicNumber)
  748.             {
  749.                 count++;
  750.             }
  751.         }
  752.     }
  753.     return count;
  754. }
  755. //+------------------------------------------------------------------+
  756. //| 交易事务函数                                                       |
  757. //+------------------------------------------------------------------+
  758. void OnTradeTransaction(const MqlTradeTransaction& trans,
  759.                        const MqlTradeRequest& request,
  760.                        const MqlTradeResult& result)
  761. {
  762.     if(trans.type == TRADE_TRANSACTION_DEAL_ADD)
  763.     {
  764.         if(HistoryDealSelect(trans.deal))
  765.         {
  766.             string symbol = HistoryDealGetString(trans.deal, DEAL_SYMBOL);
  767.             if(symbol == _Symbol)
  768.             {
  769.                 long magic = HistoryDealGetInteger(trans.deal, DEAL_MAGIC);
  770.                 if(magic == InpMagicNumber)
  771.                 {
  772.                     double profit = HistoryDealGetDouble(trans.deal, DEAL_PROFIT);
  773.                     if(profit != 0.0)
  774.                     {
  775.                         Print("动态网格交易完成 - 盈亏: ", profit, " ", AccountInfoString(ACCOUNT_CURRENCY));
  776.                         // 网格交易统计
  777.                         static int grid_trades = 0;
  778.                         static double grid_profit = 0;
  779.                         grid_trades++;
  780.                         grid_profit += profit;
  781.                         if(grid_trades % 5 == 0)
  782.                         {
  783.                             Print("网格交易统计 - 总数: ", grid_trades, " 总盈亏: ", DoubleToString(grid_profit, 2));
  784.                             Print("当前网格状态: ", g_market_state == MARKET_RANGING ? "震荡" :
  785.                                   g_market_state == MARKET_TRENDING_UP ? "上涨" :
  786.                                   g_market_state == MARKET_TRENDING_DOWN ? "下跌" : "高波动");
  787.                         }
  788.                     }
  789.                 }
  790.             }
  791.         }
  792.     }
  793. }
复制代码
举报

评论 使用道具

精彩评论8

qiwen
C
| 发表于 2025-8-23 16:10:32 | 显示全部楼层
楼主直接发出代码,太伟大了
举报

点赞 评论 使用道具

henrylin9999
D
 楼主 | 发表于 2025-8-23 17:09:29 | 显示全部楼层
qiwen 发表于 2025-8-23 16:10
楼主直接发出代码,太伟大了

刚注册,请多多关照
举报

点赞 评论 使用道具

yiquanjun
C
| 发表于 2025-8-23 20:02:22 | 显示全部楼层
必须支持一下
举报

点赞 1 评论 使用道具

xzy881230
DD
| 发表于 2025-8-24 03:22:56 | 显示全部楼层
好样的
举报

点赞 评论 使用道具

shaohua
DD
| 发表于 2025-8-25 17:37:21 | 显示全部楼层
楼主直接发出代码,太伟大了  自己写的吗
举报

点赞 评论 使用道具

786438024
DDD
| 发表于 2025-8-25 22:50:27 | 显示全部楼层
牛皮。支持
举报

点赞 评论 使用道具

dawenxi
D
| 发表于 2025-8-26 03:00:00 | 显示全部楼层
88888888888888888
举报

点赞 评论 使用道具

ryanli
DD
| 发表于 2025-9-30 15:00:28 | 显示全部楼层
楼主直接发代码厚道必须给你点个赞
举报

点赞 1 评论 使用道具

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