Полезные функции от KimIV - страница 91

 

Функция CrossPointOfSections().

Эта функция вычисляет координаты точки пересечения двух отрезков. Каждый отрезок задаётся парой координат своих точек. В функцию в качестве параметров передаются три массива:

  • x - Массив абсцисс. Должен содержать четыре элемента: x[0], x[1] - абсциссы первого отрезка, x[2], x[3] - абсциссы второго отрезка.
  • y - Массив ординат. Должен содержать четыре элемента: y[0], y[1] - ординаты первого отрезка, y[0], y[1] - ординаты второго отрезка.
  • t - Массив координат искомой точки пересечения. После нормального исполнения функции данный массив будет содержать два элемента: t[0] - абсцисса искомой точки пересечения двух прямых и t[1] - ордината этой же точки.
  • результат -- true, если отрезки пересекаются, false, если нет. Если отрезки совпадают, полностью или частично, функция вернет false.
//+----------------------------------------------------------------------------+
//|  Параметры:                                                                |
//|    x - массив абсцисс              x[0], x[1] - первый отрезок             |
//|                                    x[2], x[3] - второй отрезок             |
//|    y - массив ординат              y[0], y[1] - первый отрезок             |
//|                                    y[0], y[1] - второй отрезок             |
//|    t - массив искомых координат    t[0]       - абсцисса точки пересечения |
//|                                    t[1]       - ордината точки пересечения |
//|    результат                       true если отрезки пересекаются          |
//|                                    false если нет                          |
//|    примечание                      если отрезки не пересекаются, то в мас- |
//|                                    сив t[] передается точка пересечения    |
//|                                    прямых, на которых лежат отрезки        |
//+----------------------------------------------------------------------------+

bool CrossPointOfSections(double& x[], double& y[], double& t[]) 
{
   double z=(y[3]-y[2])*(x[1]-x[0])-(y[1]-y[0])*(x[3]-x[2]);
   ArrayResize(t, 2);
   ArrayInitialize(t, 0.0);

   if (z==0) 
   {
      Print("CrossPointOfSections(): Не удалось найти точку пересечения!");
      return (false);
   }

   double xy1=x[1]*y[0]-x[0]*y[1];
   double xy2=x[3]*y[2]-x[2]*y[3];
   t[0]=NormalizeDouble((xy1*(x[3]-x[2])-xy2*(x[1]-x[0]))/z, 0);
   t[1]=(xy1*(y[3]-y[2])-xy2*(y[1]-y[0]))/z;
   
   if ((t[0] - x[0])*(t[0] - x[1]) > 0 || (t[1] - y[0])*(t[1] - y[1]) > 0) return (false);
   if ((t[0] - x[2])*(t[0] - x[3]) > 0 || (t[1] - y[2])*(t[1] - y[3]) > 0) return (false);

   return (true);
}

Скрипт для тестирования.

Файлы:
 
Спасибо.
 

Добрый день. Вопрос по функциям, возвращающим флаг закрытия последней позиции по тейку или стоплоссу.

'Полезные функции от KimIV'

Функция isCloseLastPosByTake().
Эта функция возвращает флаг закрытия последней позиции по тейку. Флаг поднят - True - сработал TakeProfit. Флаг опущен - False - позиция была закрыта по другой причине

//---------------------------------------------------------------

Уже ставил вчера вопрос на общем форуме. Но ответа не нашлось пока.

В МОЕМ советнике 3-х ступенчатый мартингейл. Каждая ступень (позиция) имеет свой магик (1,2,3).

Позиции закрываются по сигналам и/или  по стопам.. 

Предусмотрено, также,  такое закрытие:

if (isCloseLastPosByStop(NULL, OP_BUY, Magic_3)) //если посл. позиция 
//закрылась по тейкпрофиту, - то закрываем все позиции
 ClosePosFirstProfit(NULL,OP_BUY, -1);   

Получается, что мой советник работает нормально до тех пор, пока последняя (самая большая позиция) ступень мартигейла - не закроется по тейкпрофиту

После чего, когда открывается очередная первая позиция (магик-1), то она сразу же закрывается, т.к. флаг функции Функции isCloseLastPosByTake()  остался  равным единице (1) !

И так до бесконечности. Открывается и закрывается.

Более того! Терминал этот флаг запоминает и даже новые удаление/установка советника не помогает (пока не поменяешь магики).

Нужно неким образом обнулить функцию isCloseLastPosByTake() после закрытия всех позиций.

Я уже мозги наизнанку вывернул. Никак не получается! 

Игорь !,  или кто-ниб.(кто сможет), пож. подскажите, как это сделать и можно ли это сделать вообще ?




 

Вроде бы, нашелся ответ на мой вопрос. Кому интересно, - вот здесь - 

'Вопрос к знатокам'

 
KimIV >>:

Примеры использования функции ModifyOrder().

Самыми первыми я решил дать примеры, о которых меня уже спрашивали неоднократно. Это открытие позиций в условиях рыночного исполнения торговых заявок Market Watch. Это когда нельзя одновременно отдать приказ на открытие позиции по рыночной цене и прикрепить к ней отложенный ордер. Такое открытие в условиях Market Watch нужно выполнять в два этапа: сначала открывать позицию, а потом прикреплять к ней отложенные ордера, то есть устанавливать ценовые уровни StopLoss и TakeProfit.

1. Купить 0.1 лота текущего инструмента и установить стоп 30 пунктов

2. Продать 0.15 лота текущего инструмента и установить SL=45, TP=99

int ti=OpenPosition(NULL, OP_SELL, 0.15);
if (OrderSelect(ti, SELECT_BY_TICKET))
  ModifyOrder(-1, Bid+45*Point, Bid-99*Point, clModifySell);

В прицепе работающий скрипт с примерами.





Доброе утро Игорю и всем, кто присутствует! Я применила эти функции в своем советнике. Всё модифицируется нормально.

До тех пор, пока я не вставила в мой советник магик !

Модифицируются все позиции нормально. Однако - 

Непонятно почему, но функция OpenPosition() - словно не видит магика и продолжает бесконечно открывать позиции одну, за другой на каждом баре.  Я уже убрала всё лишнее (думала - моя ошибка в коде).

И вставила в коммент число позиций.  Бесполезно. При очевидном наличии позиций - коммент выводит нуль:


Не могу разобраться, почему функция не видит магика! Вот код:
extern int        Magic           = 7771;
extern int        StopLoss        =200;
extern int        TakeProfit_Sell =200;
extern double     Lots_1          = 0.01;//размер лота
//--------------------------------------------------------------------+
extern string _P_Performance = "- Параметры открытия  позиций ";
extern bool       UseSound      = True;        //Использовать звуковой сигнал
extern string     NameFileSound = "expert.wav";//Наименование зву. файла откр.
color  clOpenBuy     = Blue;      // Цвет значка открытия покупки
color  clOpenSell    = Red;       // Цвет значка открытия продажи
color  clModifyBuy   = Aqua;      // Цвет значка модификации покупки
color  clModifySell  = Tomato;    // Цвет значка модификации продажи
 int    Slippage      = 10;       // Проскальзывание цены
 int    NumberOfTry   = 10;       // Количество попыток
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
//-- Подключаемые модули --

#include <stderror.mqh>
#include <stdlib.mqh>
//жжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжжж
bool   gbDisabled    = False;    // Флаг блокировки советника
double SL,TP;
int ti;
static int prevtime = 0; 

//------------------------------------------------------------
int start() {
Comment ("Количество откр. позиций = ",NumberOfPositions(NULL,OP_SELL, Magic));
if(Time[0] == prevtime)   return(0);//ждём появления нового бара
   prevtime = Time[0];//если появился новый бар , включаемся

//XXXXXXXXXXXXXXXXXXX ОТКРЫТИЕ ПОЗИЦИЙ ХХХХХХХХХХХХХХ

if(NumberOfPositions(NULL,OP_SELL, Magic)<1){//если нет открытых селл-
// позиций
SL=0;TP=0;// задаем стопы
if(StopLoss>0)   SL=Bid+Point*StopLoss;
if(TakeProfit_Sell>0) TP=Bid-Point*TakeProfit_Sell; 
//Открываем позицию селл  
 ti=OpenPosition(NULL, OP_SELL, Lots_1,Magic);
if (OrderSelect(ti, SELECT_BY_TICKET))
  ModifyOrder(-1, SL, TP, clModifySell);
 } 
 return (0);
 //-----------------Конец функции int start()-------------------------
}
// Пользовательские функции жжжжжжжжжжжжжжжжжжжжжжжжж
//Здесь только названия. Полный код ф-й - ниже в аттаче
void Message(string m) //вывод сообщ в коммент и принт
int NumberOfPositions(string sy="", int op=-1, int mn=-1)//кол-во позиций
string GetNameOP(int op)//торг. операция
int OpenPosition(string sy, int op, double ll, double sl=0, double tp=0, int mn=0)
void ModifyOrder(double pp=-1, double sl=0, double tp=0, color cl=CLR_NONE)
string GetNameTF(int TimeFrame=0) //таймфрейм
bool ExistPositions(string sy="", int op=-1, int mn=-1, datetime ot=0)//флаг сущ.

В аттаче исходный файл этого кода. Пож. подскажите, где я сделала ошибку и почему советник не видит магик?

Файлы:
exp.sell.rar  4 kb
 
if(StopLoss>0)   SL=Bid+Point*StopLoss;
if(TakeProfit_Sell>0) TP=Bid-Point*TakeProfit_Sell; 
//Открываем позицию селл  
 //ti=OpenPosition(NULL, OP_SELL, Lots_1,Magic);  Ваш маджик шел в качестве стоп-лосса
 ti=OpenPosition(NULL, OP_SELL, Lots_1,SL,TP,Magic);
 
Вы в курсе, что в Вашем варианте он проверяет только наличие ордеров на продажу?
Нашел, Вы в функцию открытия позиции отправляете только четыре параметра, а надо 6.
 

Да, благодарю всех (tmp.0 & Roger)! Исправила и всё заработало так, как и должно работать. 

Виновата моя невнимательность. А вовсе не функция - OpenPosition()

SL=0;TP=0;
if(StopLoss>0)   SL=Bid+Point*StopLoss;
if(TakeProfit>0) TP=Bid-Point*TakeProfit;   
ti=OpenPosition(NULL, OP_SELL, Lots,0,0,Magic);
if (OrderSelect(ti, SELECT_BY_TICKET))
  ModifyOrder(-1, SL, TP, clModifySell);
 

Игроь, подскажите!

При использовании OrderCloseBuy - OrderCloseSell встроенный язык МКюэЛь и компилятор требуют два параметра функции (тикеты ордеров - бай и селл). Один-то тикет открытого ордера есть, а как задать второй? Или я что-то не понял - в самоучителе языка ничего не написано про эту функцию и нет примера.

Заранее спасибо!

 

А вот ещё вопрос Игорю.

Создали ли отдельную пользовательскую (или другую) функцию для переворота позиции бай-на-селл и наоборот, без обычных ОрдерКлоз - ОрдерСенд?

Причина обращения: