pip maker

前回紹介しました、PipMakerですが、エラーが出てしまうといった報告がありました。

前回記事【聖杯EAの原石!? PipMaker】へ

PMsimple

そこで、PipMakerV9-1のいろいろな機能を削って骨の部分だけのものを作りましたので公開します。

PMsimple.zipをダウンロード

パラメーター

MaxLotSize 最大ロット数
LotSize 最少ロット数
Lotincrement 増加ロット数
ProfitTarget 目標利益
Spacing 買い増し売り増しするときの必要ピプス
TrendSpacing トレンド方向のSpacing
TrendTimeFrame 移動平均の使用時間足
TrendPeriods 移動平均の計算期間

最新版PMsimple_2019

PipMakerV9-1を新MQL4でリメイクした最新版が完成しましたので公開します。

最新版【PMsimple_2019.mq4】をダウンロード

ソースコード

Dr.EADr.EA

コードはこちらじゃ

#property version   "1.00"
#property strict

enum calc_lot {Addition, Multiplication};
enum on_tick {Not, Allow};

// Regular variables
extern bool    Trade_Buy                     = true;
extern bool    Trade_Sell                    = true;

extern double  Slippage                      = 0.5;
extern string  TradeComment                  = "PMsimple";
extern int     MagicNumber                   = 20191202;

extern double  MaxLotSize                    = 5;
extern double  LotSize                       = 0.01;
extern double  LotIncrement                  = 0.01;

extern calc_lot Multiplier                   = Addition;
extern double  ProfitTarget                  = 5;
extern double  TrendProfitTarget             = 5;

extern on_tick OpenOnTick                    = Allow;
extern int     Spacing                       = 10;
extern int     TrendSpacing                  = 10;
extern double  CounterTrendMultiplier        = 2;
extern int     OrdersToClose                 = 0;
extern int     MinimumOrdersToCloseLosing    = 1;
extern int     MaxMarginPercentage           = 40;
extern ENUM_TIMEFRAMES TrendTimeFrame        = PERIOD_CURRENT;
extern int     TrendPeriods                  = 1200;

// Internal settings
datetime       g_bar_time        = 0;
static bool    g_trade_allowed   = true;
double         g_tick_price      = 0;
double         profits_buy[1][2];
double         profits_sell[1][2];              


double g_point;    // 1pipの値
int g_lot_digit;    // ロット小数桁数

int OnInit()
{
   g_point = Point;
   if (Digits % 2 == 1)
   {
      g_point *= 10;
      Slippage *= 10;
   }
   
   double lotstep = MarketInfo(Symbol(), MODE_LOTSTEP);
   if(NormalizeDouble(lotstep, 3) <= 0.001)
      g_lot_digit = 3;
   else if(NormalizeDouble(lotstep, 2) <= 0.01)
      g_lot_digit = 2;
   else if(NormalizeDouble(lotstep, 1) <= 0.1)
      g_lot_digit = 1;
   else
      g_lot_digit = 0;
      
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason)
{
}


void OnTick()
{
   int i;
   
   // Check Positions ::::::::::::::::::::::::::::::::::::::::
   
   double   lowest_buy = 0;
   double   highest_buy = 0;
   double   lowest_sell = 0;
   double   highest_sell = 0;
   
   int      highest_ticket_buy = 0;
   int      lowest_ticket_buy = 0;
   int      highest_ticket_sell = 0;
   int      lowest_ticket_sell = 0;
   
   double   highest_profit_buy = 0;
   double   lowest_profit_buy = 0;
   double   highest_profit_sell = 0;
   double   lowest_profit_sell = 0;
   
   int      pos_cnt_buy = 0;
   int      pos_cnt_sell = 0;
   
   double total_lots_buy = 0;
   double total_lots_sell = 0;
   
   int orders_total = OrdersTotal();
   ArrayResize(profits_buy, orders_total + 1);
   ArrayResize(profits_sell, orders_total + 1);
   ArrayInitialize(profits_buy, 0);
   ArrayInitialize(profits_sell, 0);
   
   for (i = orders_total - 1; i >= 0; i--)
   {
      if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false) return;
      if (OrderSymbol() != Symbol() || OrderMagicNumber() != MagicNumber) continue;
      
      double profit = OrderProfit() + OrderSwap() + OrderCommission();
      
      if (OrderType() == OP_BUY)
      {
         if (highest_buy == 0 || OrderOpenPrice() > highest_buy)
         {
            highest_buy = OrderOpenPrice();
            highest_ticket_buy = OrderTicket();
            highest_profit_buy = profit;
         }

         if (lowest_buy == 0 || OrderOpenPrice() < lowest_buy)
         {
            lowest_buy = OrderOpenPrice();
            lowest_ticket_buy = OrderTicket();
            lowest_profit_buy = profit;
         }

         profits_buy[pos_cnt_buy][0] = profit;
         profits_buy[pos_cnt_buy][1] = OrderTicket();

         pos_cnt_buy++;
         total_lots_buy += OrderLots();
         
      }

      if (OrderType() == OP_SELL)
      {
         if (highest_sell == 0 || OrderOpenPrice() > highest_sell)
         {
            highest_sell = OrderOpenPrice();
            highest_ticket_sell = OrderTicket();
            highest_profit_sell = profit;
         }

         if (lowest_sell == 0 || OrderOpenPrice() < lowest_sell)
         {
            lowest_sell = OrderOpenPrice();
            lowest_ticket_sell = OrderTicket();
            lowest_profit_sell = profit;
         }

         profits_sell[pos_cnt_sell][0] = profit;
         profits_sell[pos_cnt_sell][1] = OrderTicket();

         pos_cnt_sell++;
         total_lots_sell += OrderLots();
      }
   }

   ArraySort(profits_buy, WHOLE_ARRAY, 0, MODE_DESCEND);
   ArraySort(profits_sell, WHOLE_ARRAY, 0, MODE_DESCEND);
   
   
   // Calc Profit ::::::::::::::::::::::::::::::::::::::::::::
   
   int pos_cnt_to_close;
   
   if (OrdersToClose > 0)
      pos_cnt_to_close = MathMin(orders_total + 1, OrdersToClose);
   else
      pos_cnt_to_close = orders_total + 1;

   double pos_profit_buy = 0;
   double pos_profit_sell = 0;
   
   for (i = 0; i < pos_cnt_to_close; i++)
   {
      if (profits_buy[i][0] > 0) pos_profit_buy += profits_buy[i][0];
      if (profits_sell[i][0] > 0) pos_profit_sell += profits_sell[i][0];
   }
   
   
   // Calc Middle Point ::::::::::::::::::::::::::::::::::::::
   
   double high_point = MathMax(highest_buy, highest_sell);
   double low_point = lowest_buy;
   if (lowest_sell > 0 && (low_point == 0 || low_point > lowest_sell)) low_point = lowest_sell;
   double mid_point = (high_point + low_point) / 2;
   
   
   // Exit :::::::::::::::::::::::::::::::::::::::::::::::::::
   
   bool exit_tick_buy = false;
   bool exit_tick_sell = false;

   RefreshRates();

   if (pos_cnt_buy + pos_cnt_sell > MinimumOrdersToCloseLosing)
   {
      if (Ask > mid_point)
      {
         if (lowest_sell > 0 && (lowest_sell < lowest_buy || lowest_buy == 0))
         {
            if (pos_profit_buy + lowest_profit_sell >= ProfitTarget)
            {
               if (OrderSelect(lowest_ticket_sell, SELECT_BY_TICKET) == true)
               {
                  if (OrderClose(OrderTicket(), OrderLots(), Ask, (int)Slippage, clrGreen) == true)
                  {
                     CloseBuysInProfit();
                     exit_tick_buy = true;
                     exit_tick_sell = true;
                  }
               }
            }
            else if (pos_profit_sell + lowest_profit_sell >= ProfitTarget)
            {
               if (OrderSelect(lowest_ticket_sell, SELECT_BY_TICKET) == true)
               {
                  if (OrderClose(OrderTicket(), OrderLots(), Ask, (int)Slippage, clrRed) == true)
                  {
                     CloseSellsInProfit();
                     exit_tick_sell = true;
                  }
               }
            }
         }
         else if (lowest_buy > 0 && (lowest_buy < lowest_sell || lowest_sell == 0))
         {
            if (pos_profit_buy + lowest_profit_buy >= ProfitTarget)
            {
               if (OrderSelect(lowest_ticket_buy, SELECT_BY_TICKET) == true)
               {
                  if (OrderClose(OrderTicket(), OrderLots(), Bid, (int)Slippage, clrGreen) == true)
                  {
                     CloseBuysInProfit();
                     exit_tick_buy = true;
                  }
               }
            }
            else if (pos_profit_sell + lowest_profit_buy >= ProfitTarget)
            {
               if (OrderSelect(lowest_ticket_buy, SELECT_BY_TICKET) == true)
               {
                  if (OrderClose(OrderTicket(), OrderLots(), Bid, (int)Slippage, clrRed) == true)
                  {
                     CloseSellsInProfit();
                     exit_tick_sell = true;
                     exit_tick_buy = true;
                  }
               }
            }
         }
      }
      else if (Bid < mid_point)
      {
         if (highest_buy > highest_sell)
         {
            if (pos_profit_buy + highest_profit_buy >= ProfitTarget)
            {
               if (OrderSelect(highest_ticket_buy, SELECT_BY_TICKET) == true)
               {
                  if (OrderClose(OrderTicket(), OrderLots(), Bid, (int)Slippage, clrGreen) == true)
                  {
                     CloseBuysInProfit();
                     exit_tick_buy = true;
                  }
               }
            }
            else if (pos_profit_sell + highest_profit_buy >= ProfitTarget)
            {
               if (OrderSelect(highest_ticket_buy, SELECT_BY_TICKET) == true)
               {
                  if (OrderClose(OrderTicket(), OrderLots(), Bid, (int)Slippage, clrRed) == true)
                  {
                     CloseSellsInProfit();
                     exit_tick_sell = true;
                     exit_tick_buy = true;
                  }
               }
            }
         }
         else if (highest_sell > highest_buy)
         {
            if (pos_profit_buy + highest_profit_sell >= ProfitTarget)
            {
               if (OrderSelect(highest_ticket_sell, SELECT_BY_TICKET) == true)
               {
                  if (OrderClose(OrderTicket(), OrderLots(), Ask, (int)Slippage, clrGreen) == true)
                  {
                     CloseBuysInProfit();
                     exit_tick_buy = true;
                     exit_tick_sell = true;
                  }
               }
            }
            else if (pos_profit_sell + highest_profit_sell >= ProfitTarget)
            {
               if (OrderSelect(highest_ticket_sell, SELECT_BY_TICKET) == true)
               {
                  if (OrderClose(OrderTicket(), OrderLots(), Ask, (int)Slippage, clrRed) == true)
                  {
                     CloseSellsInProfit();
                     exit_tick_sell = true;
                  }
               }
            }
         }
      }
   }
   else if (pos_cnt_buy + pos_cnt_sell < MinimumOrdersToCloseLosing)
   {      
      if (pos_profit_buy >= TrendProfitTarget)
      {
         CloseBuysInProfit();
         exit_tick_buy = true;
      }
      else if (pos_profit_sell >= TrendProfitTarget)
      {
         CloseSellsInProfit();
         exit_tick_sell = true;
      }
   }
   
   
   // Entry ::::::::::::::::::::::::::::::::::::::::::::::::::::
   
   RefreshRates();

   double ma_0 = iMA(Symbol(), TrendTimeFrame, TrendPeriods, 0, MODE_LWMA, PRICE_CLOSE, 0);
   double ma_1 = iMA(Symbol(), TrendTimeFrame, TrendPeriods, 0, MODE_LWMA, PRICE_CLOSE, 1);
   
   if (ma_0 == 0) return;
   
   // BUY Trade
   if (Trade_Buy == true && exit_tick_buy == false)
   {
      if (Ask < lowest_buy - (Spacing * g_point) || Ask > highest_buy + (TrendSpacing * g_point))
      {
         if (OpenOnTick == 1 && g_tick_price > 0 && Close[0] < g_tick_price) g_trade_allowed = true;
         
         if (ma_1 <= ma_0)
            if (total_lots_buy * MarketInfo(Symbol(), MODE_MARGINREQUIRED) <= (AccountBalance() * MaxMarginPercentage / 100) / 2)
               Order_Buy(pos_cnt_buy, lowest_buy, highest_buy);
      }
   }

   // SELL Trade
   if (Trade_Sell == true && exit_tick_sell == false)
   {
      if (Bid > highest_sell + (Spacing * g_point) || Bid < lowest_sell - (TrendSpacing * g_point))
      {
         if (OpenOnTick == 1 && g_tick_price > 0 && Close[0] > g_tick_price) g_trade_allowed = true;
         
         if (ma_1 >= ma_0)
            if (total_lots_sell * MarketInfo(Symbol(), MODE_MARGINREQUIRED) <= (AccountBalance() * MaxMarginPercentage / 100) / 2)
               Order_Sell(pos_cnt_sell, lowest_sell, highest_sell);
      }
   }
}


void CloseBuysInProfit()
{
   RefreshRates();
   
   for (int i = 0; i < ArrayRange(profits_buy, 0); i++)
   {
      if (OrdersToClose != 0 && i >= OrdersToClose) break;
      
      if (profits_buy[i][0] > 0)
         if (OrderSelect((int)profits_buy[i][1], SELECT_BY_TICKET) == true)
            if (OrderClose(OrderTicket(), OrderLots(), Bid, (int)Slippage, clrGreen) == false) Print("OrderClose error.");
   }
}


void CloseSellsInProfit()
{
   RefreshRates();
   
   for (int i = 0; i < ArrayRange(profits_sell, 0); i++)
   {
      if (OrdersToClose != 0 && i >= OrdersToClose) break;
      
      if (profits_sell[i][0] > 0)
         if (OrderSelect((int)profits_sell[i][1], SELECT_BY_TICKET) == true)
            if (OrderClose(OrderTicket(), OrderLots(), Ask, (int)Slippage, clrRed) == false) Print("OrderClose error.");
   }
}


void Order_Buy(int pos_cnt_buy, double lowest_buy, double highest_buy)
{
   if (g_bar_time != Time[0])
   {
      g_bar_time = Time[0];
      g_tick_price = 0;
      g_trade_allowed = true;
   }
   if (g_trade_allowed == false) return;

   RefreshRates();
   
   double lots = 0;
   
   if (pos_cnt_buy > 0 && Ask > highest_buy)
   {
      if (Multiplier == Multiplication)
         lots = NormalizeDouble(LotSize * MathPow(LotIncrement, pos_cnt_buy), g_lot_digit);
      else
         lots = NormalizeDouble(LotSize + (LotIncrement * pos_cnt_buy), g_lot_digit);
   }
   else
   {
      if (Multiplier == Multiplication)
         lots = NormalizeDouble(LotSize * CounterTrendMultiplier * MathPow(LotIncrement, pos_cnt_buy), g_lot_digit);
      else
         lots = NormalizeDouble((LotSize * CounterTrendMultiplier) + (LotIncrement * pos_cnt_buy), g_lot_digit);
   }

   if (lots == 0) lots = NormalizeDouble(LotSize, g_lot_digit);
   if (lots > MaxLotSize) lots = MaxLotSize;

   int ticket = OrderSend(Symbol(), OP_BUY, lots, Ask, (int)Slippage, 0, 0, TradeComment, MagicNumber, clrGreen);
   if (ticket > 0)
   {
      g_tick_price = Close[0];
      g_trade_allowed = false;
   }
}


void Order_Sell(int pos_cnt_sell, double lowest_sell, double highest_sell)
{
   if (g_bar_time != Time[0])
   {
      g_bar_time = Time[0];
      g_tick_price = 0;
      g_trade_allowed = true;
   }
   if (g_trade_allowed == false) return;

   RefreshRates();
   
   double lots = 0;
   
   if (pos_cnt_sell > 0 && Bid < lowest_sell)
   {
      if (Multiplier == Multiplication)
      lots = NormalizeDouble(LotSize * MathPow(LotIncrement, pos_cnt_sell), g_lot_digit);
      else
      lots = NormalizeDouble(LotSize + (LotIncrement * pos_cnt_sell), g_lot_digit);
   }
   
   if (pos_cnt_sell == 0 || Bid > highest_sell)
   {
      if (Multiplier == Multiplication)
      lots = NormalizeDouble(LotSize * CounterTrendMultiplier * MathPow(LotIncrement, pos_cnt_sell), g_lot_digit);
      else
      lots = NormalizeDouble((LotSize * CounterTrendMultiplier) + (LotIncrement * pos_cnt_sell), g_lot_digit);
   }

   if (lots == 0) lots = NormalizeDouble(LotSize, g_lot_digit);
   if (lots > MaxLotSize) lots = MaxLotSize;

   int ticket = OrderSend(Symbol(), OP_SELL, lots, Bid, (int)Slippage, 0, 0, TradeComment, MagicNumber, clrRed);
   if (ticket > 0)
   {
      g_tick_price = Close[0];
      g_trade_allowed = false;
   }
}

また、報告お願い致しますm(..)m