MQL4、MQL5に関する初心者からの質問、アルゴリズムやコードに関するヘルプ、ディスカッションなど。 - ページ 1549

 
MakarFX:

分かっているのに話すのは良くない...。

は、「有益な情報をできるだけ多く出す」ためのアドバイスをしてください。

はっきり言ってしまいましたね。では、あなた個人についてお聞きします。

以下は2つの機能で、どちらも過去の注文を 通過するものです。

//+------------------------------------------------------------------+
//|  Возвращает пункты убытка закрытых ордеров с начала цикла        |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//|  Возвращает кол-во серии убыточных ордеров                       |
//+------------------------------------------------------------------+

同じオーダーで2サイクル。これらの関数が返すすべてを1回のサイクルで得ることはできませんよね。

 

押忍

フクロウにトレードリバーサルを追加しようとしています。説明書に書いてある通りにやっていますhttps://www.mql5.com/ru/forum/128200

コンパイル時のエラーはないのですが、テスターでフリップが動作しません。

ログにエラーが表示される。

2021.07.29 20:06:34.316 2015.01.08 22:10:00 フリップスルーコード付きSMA AUDUSD,M5: OrderSend error 130

2021.07.29 20:06:34.316 2015.01.08 22:05:45 SMA with reversal via AUDUSD,M5: OrderSend error 4107

2021.07.29 20:06:34.316 2015.01.08 22:05:45 SMA with flip via AUDUSD,M5: invalid stoploss for OrderSend function.

何が問題なのか、教えていただけませんか?

で指定された変数が、その変数に対応したものであると、私自身は考えています。

int ReversOrderSend (string symbol,int cmd,double volume,double price,int slippage,double stoploss,double takeprofit,string comment,int magic=0,datetime expiration=0,カラー arrow_color=CLR_NONE)

メインコードに関連しないもの。

異なる端末、4サイン、5サインで試しました。

これがコードの全体像です。

//+-----------------------------------------------------------------------------------------------+
//|                                                                     Simple Moving Average.mq4 |
//|                                                                 Copyright 2016, Andrey Minaev |
//|                                                     https://www.mql5.com/ru/users/id.scorpion |
//+-----------------------------------------------------------------------------------------------+
#property copyright "Copyright 2016, Andrey Minaev"
#property link      "https://www.mql5.com/ru/users/id.scorpion"
#property version   "1.00"
#property strict

// Параметры советника
extern string sParametersEA = "";     // Параметры советника
extern double dLots         = 0.01;   // Количество лотов
extern int    iStopLoss     = 30;     // Уровень убытка (в пунктах)
extern int    iTakeProfit   = 30;     // Уровень прибыли (в пунктах)
extern int    iSlippage     = 3;      // Проскальзование (в пунктах)
extern int    iMagic        = 1;      // Индентификатор советника
extern double K_Martin     = 2.0;
extern int    OrdersClose  = 5;
extern int    DigitsLot    = 2;
extern int    ReversOrder  = 0;             // Переворот сделок 1-да; 0-нет;
// Параметры индикатора
extern string sParametersMA = "";     // Параметры индикатора
extern int    iPeriodMA     = 14;     // Период усреднения
// Глобальные переменные
double dMA;
//+-----------------------------------------------------------------------------------------------+
int OnInit()
  {
// Если брокер использует 3 или 5 знаков после запятой, то умножаем на 10
   if(Digits == 3 || Digits == 5)
     {
      iStopLoss   *= 10;
      iTakeProfit *= 10;
      iSlippage   *= 10;
     }

   return(INIT_SUCCEEDED);
  }
//+-----------------------------------------------------------------------------------------------+
void OnDeinit(const int reason)
  {

  }
//+-----------------------------------------------------------------------------------------------+
void OnTick()
  {
// Получим значение индикатора
   dMA = iMA(Symbol(), 0, iPeriodMA, 0, MODE_SMA, PRICE_CLOSE, 0);

// Если нет открытых ордеров, то входим в условие
   if(bCheckOrders() == true)
     {
      // Если появился сигнал на покупку, то откроем ордер на покупку
      if(bSignalBuy() == true)
         vOrderOpenBuy();

      // Если появился сигнал на продажу, то откроем ордер на продажу
      if(bSignalSell() == true)
         vOrderOpenSell();
     }
  }
//+-----------------------------------------------------------------------------------------------+
//|                                                             Функция проверки открытых оредров |
//+-----------------------------------------------------------------------------------------------+
bool bCheckOrders()
  {
// Переберем в цикле ордера, для проверки открытых ордеров данным советником
   for(int i = 0; i <= OrdersTotal(); i++)
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == iMagic)
            return(false);

   return(true);
  }
//+-----------------------------------------------------------------------------------------------+
//|                                                             Функция поиска сигнала на покупку |
//+-----------------------------------------------------------------------------------------------+
bool bSignalBuy()
  {
   if(dMA > Open[1] && dMA < Close[1])
      return(true);

   return(false);
  }
//+-----------------------------------------------------------------------------------------------+
//|                                                             Функция поиска сигнала на продажу |
//+-----------------------------------------------------------------------------------------------+
bool bSignalSell()
  {
   if(dMA < Open[1] && dMA > Close[1])
      return(true);

   return(false);
  }
//+-----------------------------------------------------------------------------------------------+
//|                                                            Функция открытия ордера на покупку |
//+-----------------------------------------------------------------------------------------------+
void vOrderOpenBuy()
  {
   int iOTi = 0;   // Тикет ордера

   iOTi = ReversOrderSend(Symbol(), OP_BUY, LOT(), Ask, iSlippage, 0, 0, "", iMagic, 0, clrNONE);

// Проверим открылся ли ордер
   if(iOTi > 0)
      // Есди да, то выставим уровни убытка и прибыли
      vOrderModify(iOTi);
   else
      // Если нет, то получим ошибку
      vError(GetLastError());
  }
//+-----------------------------------------------------------------------------------------------+
//|                                                            Функция открытия ордера на продажу |
//+-----------------------------------------------------------------------------------------------+
void vOrderOpenSell()
  {
   int iOTi = 0;   // Тикет ордера

   iOTi = ReversOrderSend(Symbol(), OP_SELL, LOT(), Bid, iSlippage, 0, 0, "", iMagic, 0, clrNONE);

// Проверим открылся ли ордер
   if(iOTi > 0)
      // Есди да, то выставим уровни убытка и прибыли
      vOrderModify(iOTi);
   else
      // Если нет, то получим ошибку
      vError(GetLastError());
  }
//+-----------------------------------------------------------------------------------------------+
//|                                                                    Функция модификации ордера |
//+-----------------------------------------------------------------------------------------------+
void vOrderModify(int iOTi)
  {
   int    iOTy = -1;   // Тип ордера
   double dOOP = 0;    // Цена открытия ордера
   double dOSL = 0;    // Стоп Лосс
   int    iMag = 0;    // Идентификатор советника

   double dSL = 0;     // Уровень убытка
   double dTP = 0;     // Уровень прибыли

// Выберем по тикету открытый ордер, получим некоторые значения
   if(OrderSelect(iOTi, SELECT_BY_TICKET, MODE_TRADES))
     {
      iOTy = OrderType();
      dOOP = OrderOpenPrice();
      dOSL = OrderStopLoss();
      iMag = OrderMagicNumber();
     }

// Если ордер открыл данный советник, то входим в условие
   if(OrderSymbol() == Symbol() && OrderMagicNumber() == iMag)
     {
      // Если Стоп Лосс текущего ордера равен нулю, то модифицируем ордер
      if(dOSL == 0)
        {
         if(iOTy == OP_BUY)
           {
            dSL = NormalizeDouble(dOOP - iStopLoss * Point, Digits);
            dTP = NormalizeDouble(dOOP + iTakeProfit * Point, Digits);

            bool bOM = OrderModify(iOTi, dOOP, dSL, dTP, 0, clrNONE);
           }

         if(iOTy == OP_SELL)
           {
            dSL = NormalizeDouble(dOOP + iStopLoss * Point, Digits);
            dTP = NormalizeDouble(dOOP - iTakeProfit * Point, Digits);

            bool bOM = OrderModify(iOTi, dOOP, dSL, dTP, 0, clrNONE);
           }
        }
     }
  }
//+-----------------------------------------------------------------------------------------------+
//|                                                                      Функция обработки ошибок |
//+-----------------------------------------------------------------------------------------------+
void vError(int iErr)
  {
   switch(iErr)
     {
      case 129:   // Неправильная цена
      case 135:   // Цена изменилась
      case 136:   // Нет цен
      case 138:   // Новые цены
         Sleep(1000);
         RefreshRates();
         break;

      case 137:   // Брокер занят
      case 146:   // Подсистема торговли занята
         Sleep(3000);
         RefreshRates();
         break;
     }
  }
//+-----------------------------------------------------------------------------------------------+

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double LOT()
  {
   int n=0;
   double OL=dLots;
   for(int j = OrdersHistoryTotal()-1; j >= 0; j--)
     {
      if(OrderSelect(j, SELECT_BY_POS,MODE_HISTORY))
        {
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == iMagic)
           {
            if(OrderProfit()<0)
              {
               if(n==0)
                  OL=NormalizeDouble(OrderLots()*K_Martin,DigitsLot);
               n++;
               if(n>=OrdersClose)
                 {
                  Comment("1");
                  return(dLots);
                 }
              }
            else
              {
               if(n==0)
                 {
                  Comment("2");
                  return(dLots);
                 }
               else
                 {
                  Comment("3");
                  return(OL);
                 }
              }
           }
        }
     }
   return(OL);
  }
//------------------------------------------------------------------
int ReversOrderSend (string symbol,int cmd,double volume,double price,int slippage,double stoploss,double takeprofit,string comment,int magic=0,datetime expiration=0,color arrow_color=CLR_NONE)
{
int Ret=0;
double sprd=MarketInfo(symbol,MODE_SPREAD)*Point;
//Print ("----------------------------",sprd);
if (ReversOrder==0) // Открываем ордера без разворота
{
Ret=OrderSend (symbol,cmd,volume,price,slippage,stoploss,takeprofit,comment,magic,expiration,arrow_color);
}
if (ReversOrder==1)
{
///////////////
if (cmd==OP_SELLSTOP) // Переворачиваем ордера OP_SELLSTOP
{
Ret=OrderSend (symbol,OP_BUYLIMIT,volume,price+sprd,slippage,takeprofit-sprd,stoploss-sprd,comment,magic,expiration,arrow_color);
}
if (cmd==OP_BUYSTOP) // Переворачиваем ордера OP_BUYSTOP
{
Ret=OrderSend (symbol,OP_SELLLIMIT,volume,price-sprd,slippage,takeprofit+sprd,stoploss+sprd,comment,magic,expiration,arrow_color);
}
///////////////
if (cmd==OP_SELL) // Переворачиваем ордера OP_SELL
{
Ret=OrderSend (symbol,OP_BUY,volume,price+sprd,slippage,takeprofit-sprd,stoploss-sprd,comment,magic,expiration,arrow_color);
}
if (cmd==OP_BUY) // Переворачиваем ордера OP_BUY
{
Ret=OrderSend (symbol,OP_SELL,volume,price-sprd,slippage,takeprofit+sprd,stoploss+sprd,comment,magic,expiration,arrow_color);
}
//////////////
if (cmd==OP_SELLLIMIT) // Переворачиваем ордера OP_SELLLIMIT
{
Ret=OrderSend (symbol,OP_BUYSTOP,volume,price+sprd,slippage,takeprofit-sprd,stoploss-sprd,comment,magic,expiration,arrow_color);
}
if (cmd==OP_BUYLIMIT) // Переворачиваем ордера OP_BUYLIMIT
{
Ret=OrderSend (symbol,OP_SELLSTOP,volume,price-sprd,slippage,takeprofit+sprd,stoploss+sprd,comment,magic,expiration,arrow_color);
}
}
return (Ret);
}
Предлагаю функцию реверса ордеров, для сливающих советников.
Предлагаю функцию реверса ордеров, для сливающих советников.
  • 2010.08.24
  • www.mql5.com
Помню, поначалу сталкивался с вопросом, как грамотно "перевернуть" ордера с покупки на продажу и наоборот...
 
Alexey Viktorov:

もう、はっきり言ってしまいましたね。個人的な質問をさせていただきます。

以下は2つの関数で、どちらも過去の注文を 循環させます。

同じオーダーに2つのループがある。これらの関数が返すすべてを、1回のサイクルで得ることはできませんよね。

Alexei、私はすでに書きましたが、あなたが良いプログラマーであることは知っていますよ。

しかし、私はプログラマーではありませんし、あなたにとって「十分明確」なことが、私にとっては「あまり明確」ではないのです...。

2つのループについては、異なるタイプのデータを返すので、私にとっては「1つのループですべてを取得する」 ことは不可能です。

 
MakarFX:

Alexey、私はすでに書きましたが、あなたが良いプログラマーであることは知っていますよ。

でも、私はプログラマーではないので、あなたにとっては「十分クリア」なことでも、私にとっては「暗い森」なんです...。

2つのループについては、異なるデータ型を返すので、私にとっては「1つのループですべてを取得する」 ことは不可能です。

返却されたタイプは関係ない。同じデータに対して、異なるチェックとフィルタで2つのループがある場合、常に1つのループにすべてを入れることができますが、コードはあまり明確に読めなくなりますが、動作は速くなります)デバッグの段階では、1つのループですべてを行うことはありません。違うものの方が、バグを見つけやすいのです。

 
MakarFX:

Alexey、私はすでに書きましたが、あなたが良いプログラマーであることは知っていますよ。

でも、私はプログラマーではないので、あなたにとっては「十分クリア」なことでも、私にとっては「暗い森」なんです...。

2つのループについては、異なるタイプのデータを返すため、私にとっては「1つのループですべてを取得する」 ことは不可能です。

私は2つのバリエーションを持っています。

  1. グローバルレベルで変数を作る。そうすれば、すべての機能で利用できるようになります。
  2. ローカル変数を 参照渡しする。そして、この変数を変更すると、ローカル変数も変更されます。
    /********************Script program start function*******************/
    void OnStart()
     {
      int a = 0;
      f_0(a);
      Print(a);
     }/******************************************************************/
    
    void f_0(int & b)
     {
      b = 100;
     }
    そして、そのような変数は最大で64個あるかもしれない、神は私が嘘をつくことを禁じている。間違っていたら、どなたか訂正してください。
  3. ドキュメントをもっと注意深く読んでください。そこには詳細に書かれている。
 
MakarFX:

保留中の注文が競合しているのですが。

最初の結果です。 通貨ペア間の競合があり、EAは保留注文の 配置で競合しています。 例えば、私はEURUSDの保留注文を配置し、EAはアルゴリズムに従っています(1.18901で買い、オープンポジション、EAは1.18751でストップ、1.19051で利益を取り、1.18751で売り注文)すべては計画通りに大丈夫です。

しかし、今度は価格が異なるGBPUSDで取引を開始するときです。EAは、保留中の注文を設定することを除いて、すべて正しく動作しています。1.39393の売り注文がトリガーされ、EAはそれを開き、1.39633にストップを設定し、1.39153を取ろうとしたが、1.3963の買い注文はEURUSDで完全に重複し、1.18751の売り注文がある)

EURUSDのオープントレードで、1.18751にストップ、1.18901に売り保留、1.18595に取るとトリガーされたことです。Expert Advisorは、履歴にあるトリガーされたストップをテイクに追加していません。

これらが問題なのです。

 
законопослушный гражданин:

押忍

フクロウにトレードのフリップを ねじ込むようにしています。

どういうことですか?ある一定の価格帯から購入/販売するのか?

 
SGarnov:

こんにちは。EAに協力してください。ストラテジーによれば、ストップがトリガーされた場合、EAはIDで履歴から次の設定された持ち点に(ポイント数)
を追加するはずですが、なぜか実行されないのです。

コードのどこがおかしいのでしょうか?

if(isLimitOn && OrderSelect(OrderMagicNumber(), SELECT_BY_TICKET, MODE_HISTORY)){
            tpc += stop_loss;
            if(OrderSelect(lastMagic, SELECT_BY_TICKET)){
               if(OrderType() == OP_BUY) {
                  double tp_price = NormalizeDouble((OrderOpenPrice() + Point() * (tp + tpc)), Digits);
                  if(!OrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss(), tp_price, OrderExpiration()))
                     Print("Ошибка модификации ордера:", GetLastError());
               }else if(OrderType() == OP_SELL){
                  double tp_price = NormalizeDouble((OrderOpenPrice() - Point() * (tp + tpc)), Digits);
                  if(!OrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss(), tp_price, OrderExpiration()))
                     Print("Ошибка модификации ордера:", GetLastError());
               }
            }
               
            isLimitOn = false;
         }

MakarはOrderMagicNumber()を正しく指摘したが、エラーを誤解していた。この関数の構文はドキュメントを読んでください...注文リストのインデックスか、ある注文のチケットの どちらかになるはずですが、マジコンではありません。また、OrderTicket()はここでは役に立ちません。そこに置こうとしないでください。

 
SGarnov:

どういうことですか?購入/売却する価格帯が決まっている?

このコードの作者は、私の理解では、次のような提案をしています。

フクロウがストップ&テイクで買い取引を開始した場合、彼のコードは同じ場所で 同時に売り取引を開始します(スプレッドを考慮して)買い取引の 代わりにストップ&テイクで。

このように、EAのエントリーポイント探しのロジックは変わらず、スプレッドが考慮された方向のみが変化します。

これこそ私が必要としているものだ

 
MakarFX:

このEAに何を求めるか(運用のロジック)を端的に記述してください。

コードに不要なものが多いのか、何か理解できていないようです。

フクロウは、独自のアルゴリズムに従って取引を開始する必要があります。

ストップがかかれば、次の取引はマーチンで、というように、指定した倍率になるまで(関数 -OrdersClose = ......;)

さらに、ターミナルと一緒にフクロウが無効になっている場合、別のフクロウで「自動取引」ボタンを押すだけで、次の取引はマーチンゲールによって増加した最後のロットではなく、開始ロットから開始されます。

また、スケジュールを付けられるといいのですが、このアイデアは今思いついたものです。

例えば、月曜日の10時からスタートロットで起動し、日中に何らかの結果が出たのでスイッチを切り、火曜日の朝10時に再び起動し、スタートロットでスタートさせるといった具合です。

すべてです。