Стратегии и роботы > Усреднение!

Обсуждение, описание стратегий и роботов, идеи для стратегий
Orange2000
Сообщения: 44
Зарегистрирован: 13 мар 2019, 00:45
Благодарил (а): 36 раз
Поблагодарили: 1 раз

Re: Усреднение!

Непрочитанное сообщение Orange2000 » 22 апр 2020, 20:51

Евгений, все работает как надо.
Я хотел узнать именно по стратегии с закрытием в конце дня. Правильно я понимаю, что робот на основе этой стратегии при запуске например днем, пересчитывает позиции (виртуально) с утра , что бы принять решение, что делать?

Просто ситуация такая сегодня: Торгую минутки фьюча газа. Максимальный объем набираемый 10 лотов.
Утром запустил робота. Гэп вниз, робот берет лонг 1 порцию. Мы идем вверх, он продает и начинает набирать шорт. К 11 часам уже набрано 10 лотов и фьюч идет дальше. Я вижу, что настроение бычье и где то в 12 часов выключаю робота. Нажимаю Остановить и закрыть позиции.

Фьюч ушел значительно выше. Т.е. робот бы держал в шорте 10 фьючей и накапливал бы убыток. Но я закрыл позу и выключил его.
Перезапустил АД. В районе 16-00 я понимаю, что возможно рынок уйдет в боковик. Запускаю робота а он ничего не делает)

Т.е. по идее он ждет возврата к ценам что были утром???

Аватара пользователя
evge
Администратор
Сообщения: 1652
Зарегистрирован: 04 фев 2016, 09:46
Откуда: Млечный путь, планета Земля
Благодарил (а): 64 раза
Поблагодарили: 303 раза
Контактная информация:

Re: Усреднение!

Непрочитанное сообщение evge » 23 апр 2020, 18:40

Orange2000 писал(а):Т.е. по идее он ждет возврата к ценам что были утром???


Остановка и запуск того же робота не перезапускает алгоритм.
Он помнит состояние на момент остановки в глоб. переменных.
никогда такого не было и вот опять

Konstantin
Сообщения: 17
Зарегистрирован: 11 окт 2017, 15:25
Благодарил (а): 5 раз

Re: Усреднение!

Непрочитанное сообщение Konstantin » 05 авг 2020, 19:57

evge писал(а):Тогда вот код Грааля :)

Код: Выделить всё

/**
**/

function Initialize()
{
   StrategyName = "UpAndDown";
   AddInput("Input1", Inputs.Candle, 5, true, "GAZP=МБ ЦК");
   AddParameter("StartQ", 3000, "Стартовое кол-во", 0);
   AddParameter("Q", 300, "Кол-во докупки", 0);
   AddParameter("DeltaPercent", 0.4, "% изменения цены для докупки и продажи", 0);
           
   AddGlobalVariable("xPrice", Types.Double, 10000000000.0);
   AddGlobalVariable("xPosition", Types.Double, 0.0);
   AddGlobalVariable("LastPrice", Types.DoubleList);
   AddGlobalVariable("Last", Types.Double, 0);
   AddGlobalVariable("MinPrice", Types.Double, 0);
   AddGlobalVariable("MaxPrice", Types.Double, 99999999);   
   AddGlobalVariable("Type", Types.Double, 1);
   
   AddGlobalVariable("N", Types.Int, 1); //направление "1" - Long, "-1" - Short
}

function OnUpdate()
{

// evge 13.04.2019 https://alfadirect4.ru
// модификация стратегии StepByStep от AlfaDirect

// Переворот стратегии Long/Short
if (xPosition !=0 && CurrentPosition() == 0)
{
   N =- N;
   xPrice = 10000000000.0;
   LastPrice.Clear();
   xPosition = 0;
   MaxPrice = Double.MaxValue;
   MinPrice = 0;
}

double pos = CurrentPosition();
// Правило 1. если первый запуск, покупаем  StartQ
   if ( xPrice == 10000000000.0 && N > 0)
   {
       if ( (Q%LotSize() != 0) || (StartQ%LotSize() != 0) )
       {
          ShowMessage("StartQ или Q не кратно лоту. Робот остановлен !");
          Stop();
       }
       // Покупка StartQ
       if (StartQ > 0)       
       {
         EnterLongLimit(Input1.Close[0]*(1.0 + 0.01*DeltaPercent), StartQ);
       }
         xPrice = Input1.Close[0];
    }
// Правило 1.1 старт для Short, продаем StartQ
   if ( xPrice == 10000000000.0 && N < 0)
   {
       if ( (Q%LotSize() != 0) || (StartQ%LotSize() != 0) )
       {
          ShowMessage("StartQ или Q не кратно лоту. Робот остановлен !");
          Stop();
       }
       // Продажа StartQ
       if (StartQ > 0)       
       {
         EnterShortLimit(Input1.Close[0]*(1.0 - 0.01*DeltaPercent), StartQ);
       }
         xPrice = Input1.Close[0];
    }
   
// Модуль проверки изменение позиции UP
   // если позиция выросла, добавляем уровень в список
   if (N > 0)
   {
      if ( pos > xPosition )   
      {     
           double a = xPrice;
           double b = xPosition;
                  
            while (pos - b > 0)
            {
               LastPrice.Add(a);
               a = a*(1.0 + 0.01*DeltaPercent);
               b = b + Q;
             }           
           Last = xPrice;
           xPosition = pos;             
           LastPrice.Sort();
      }
      // если позиция снизилась, убираем уровень из списка
      else if ( pos < xPosition && LastPrice.Count >= 1 )
      {
         LastPrice.Sort();
         LastPrice.RemoveAt(0);
         Last = xPrice;
         xPosition = pos;             
      }   
   
      if ( LastPrice.Count <= 0 )
          MinPrice = Last;
       else
          MinPrice = LastPrice.Min();
   }
   
// Модуль проверки изменение позиции DOWN
   // если позиция снизилась, добавляем уровень в список
   if (N < 0)
   {
      if ( pos < xPosition )   
      {     
           double a = xPrice;
           double b = xPosition;
                  
            while (pos - b < 0)
            {
               LastPrice.Add(a);
               a = a*(1.0 - 0.01*DeltaPercent);
               b = b - Q;
             }           
           Last = xPrice;
           xPosition = pos;             
           LastPrice.Sort();
           LastPrice.Reverse();
      }
      // если позиция выросла, убираем уровень из списка
      else if ( pos > xPosition && LastPrice.Count >= 1 )
      {
         LastPrice.Sort();
         LastPrice.Reverse();
         LastPrice.RemoveAt(0);
         Last = xPrice;
         xPosition = pos;             
      }   
   
      if ( LastPrice.Count <= 0 )
          MaxPrice = Last;
       else
          MaxPrice = LastPrice.Max();
   }
   
                       
//Правило 2. Если цена упала и кол-во меньше допустимого,
//           то покупаем и добавляем цену покупки в начало списка
   if ( N > 0 && Input1.Close[0] < MinPrice*(1.0 - 0.01*DeltaPercent) && pos + Q <= LongLimit )
   {
      EnterLongLimit(Input1.Close[0]*(1.0 + 0.5*0.01*DeltaPercent), Q);
        xPrice =  Input1.Close[0];
     }
//Правило 2.1. Если цена выросла и кол-во больше допустимого,
//           то продаем и добавляем цену продажи в начало списка
   if ( N < 0 && Input1.Close[0] > MaxPrice*(1.0 + 0.01*DeltaPercent) && pos - Q >= ShortLimit )
   {
      EnterShortLimit(Input1.Close[0]*(1.0 - 0.5*0.01*DeltaPercent), Q);
        xPrice =  Input1.Close[0];
     }     
//Правило 3. Если цена выше цены из начала списка, то продаем и удаляем 0-й элемент списка
   if ( N > 0 && Input1.Close[0] >= MinPrice*(1.0 + 0.01*DeltaPercent) && pos > 0 )
    {
       CloseLongLimit(Input1.Close[0]*(1.0 - 0.5*0.01*DeltaPercent), Q);
         xPrice =  Input1.Close[0];
     }
//Правило 3.1. Если цена ниже цены из начала списка, то покупаем и удаляем 0-й элемент списка
   if ( N < 0 && Input1.Close[0] <= MaxPrice*(1.0 - 0.01*DeltaPercent) && pos < 0 )
    {
       CloseShortLimit(Input1.Close[0]*(1.0 + 0.5*0.01*DeltaPercent), Q);
         xPrice =  Input1.Close[0];
     }
}



Код с параметрами по умолчанию как на графиках по GAZP выше, в тестировании не забывайте установить предельную позицию Long и Short больше стартовой (например, 5000 в обе стороны)

Этот код стартует всегда с Long.

Можно конечно доработать и сделать возможность старта в нужную сторону.


evge, можете сделать так, чтобы открытие первой сделки было не случайным, а по какому-нибудь трендовому индикатору, например, МА?
А в случае смены тренда, происходило закрытие всех позиций по этому трендовому индикатору.

Аватара пользователя
evge
Администратор
Сообщения: 1652
Зарегистрирован: 04 фев 2016, 09:46
Откуда: Млечный путь, планета Земля
Благодарил (а): 64 раза
Поблагодарили: 303 раза
Контактная информация:

Re: Усреднение!

Непрочитанное сообщение evge » 05 авг 2020, 21:44

оно не случайное, а всегда long. Можно сделать всегда short, если задать N по умолчанию -1

здесь

Код: Выделить всё

   AddGlobalVariable("N", Types.Int, -1); //направление "1" - Long, "-1" - Short


если конечно надо стартовать можно конечно задать в 0 и вначале проверять на 0 и определять начальное направление.

Не понятно что значит: если МА сменило направление, то закрыть все позиции? т.е. в противоположную сторону вообще не открывать позиции пока не сменится опять в MA в нужную сторону?
никогда такого не было и вот опять

Konstantin
Сообщения: 17
Зарегистрирован: 11 окт 2017, 15:25
Благодарил (а): 5 раз

Re: Усреднение!

Непрочитанное сообщение Konstantin » 06 авг 2020, 11:00

evge писал(а):оно не случайное, а всегда long. Можно сделать всегда short, если задать N по умолчанию -1

здесь

Код: Выделить всё

   AddGlobalVariable("N", Types.Int, -1); //направление "1" - Long, "-1" - Short


если конечно надо стартовать можно конечно задать в 0 и вначале проверять на 0 и определять начальное направление.

Не понятно что значит: если МА сменило направление, то закрыть все позиции? т.е. в противоположную сторону вообще не открывать позиции пока не сменится опять в MA в нужную сторону?



Да, верно, открывать противоположную позицию, только когда МА покажет тренд в нужную сторону. То есть можно будет выставить МА с большим периодом, а покупать/продавать на откатах, но при смене тренда, закрывать все позиции.

Торгуем в обе стороны, но по показаниям МА.

Аватара пользователя
evge
Администратор
Сообщения: 1652
Зарегистрирован: 04 фев 2016, 09:46
Откуда: Млечный путь, планета Земля
Благодарил (а): 64 раза
Поблагодарили: 303 раза
Контактная информация:

Re: Усреднение!

Непрочитанное сообщение evge » 06 авг 2020, 13:24

Будет частая смена направления и переворот позиции, на котором будет больше всего потерь.

Судя по описанию, закрытие всех позиций при смене направления MA в тоже время это и открытие по количеству StartQ в противоположную сторону.

Чуть позже сделаю.
никогда такого не было и вот опять

Аватара пользователя
evge
Администратор
Сообщения: 1652
Зарегистрирован: 04 фев 2016, 09:46
Откуда: Млечный путь, планета Земля
Благодарил (а): 64 раза
Поблагодарили: 303 раза
Контактная информация:

Re: Усреднение!

Непрочитанное сообщение evge » 06 авг 2020, 14:20

вот что-то подобное

Код: Выделить всё

function Initialize()
{
   StrategyName = "UpAndDownMA";
   AddInput("Input1", Inputs.Candle, 5, true, "GAZP=МБ ЦК");
   AddParameter("StartQ", 1500, "Стартовое кол-во", 0);
   AddParameter("Q", 300, "Кол-во докупки", 0);
   AddParameter("DeltaPercent", 0.1, "% изменения цены для докупки и продажи", 0);
   AddParameter("SMAper", 99, "MA Period", 0);
           
   AddGlobalVariable("xPrice", Types.Double, 10000000000.0);
   AddGlobalVariable("xPosition", Types.Double, 0.0);
   AddGlobalVariable("LastPrice", Types.DoubleList);
   AddGlobalVariable("Last", Types.Double, 0);
   AddGlobalVariable("MinPrice", Types.Double, 0);
   AddGlobalVariable("MaxPrice", Types.Double, 99999999);   
   AddGlobalVariable("Type", Types.Double, 1);
   
   AddGlobalVariable("N", Types.Int, 1); //направление "1" - Long, "-1" - Short
   AddChartIndicator("SMA", new Dictionary <string, string>{{"Period", "SMAper"}});
}

function OnUpdate()
{

// evge 13.04.2019 https://alfadirect4.ru
// модификация стратегии StepByStep от AlfaDirect
// evge 06.08.2020 https://alfadirect4.ru
// работа по MA

var CP = CurrentPosition();

var sMA = SMA(Input1, SMAper);
var NN = sMA[0] > sMA[1] ? 1 : sMA[0] < sMA[1] ? - 1 : N;
if (N == 0) N = NN;

// Переворот при смене направления
if (N != NN && CP > 0 && NN < 0) { ClosePosition(); xPosition = 1; N = NN; CP = 0; return; }
if (N != NN && CP < 0 && NN > 0) { ClosePosition(); xPosition = -1; N = NN; CP = 0; return; }

if (xPosition !=0 && CP == 0)
{
   //N =- N;
   xPrice = 10000000000.0;
   LastPrice.Clear();
   xPosition = 0;
   MaxPrice = Double.MaxValue;
   MinPrice = 0;
}

double pos = CurrentPosition();
// Правило 1. если первый запуск, покупаем  StartQ
   if ( xPrice == 10000000000.0 && N > 0)
   {
       if ( (Q%LotSize() != 0) || (StartQ%LotSize() != 0) )
       {
          ShowMessage("StartQ или Q не кратно лоту. Робот остановлен !");
          Stop();
       }
       // Покупка StartQ
       if (StartQ > 0)       
       {
         EnterLongLimit(Input1.Close[0]*(1.0 + 0.01*DeltaPercent), StartQ);
       }
         xPrice = Input1.Close[0];
    }
// Правило 1.1 старт для Short, продаем StartQ
   if ( xPrice == 10000000000.0 && N < 0)
   {
       if ( (Q%LotSize() != 0) || (StartQ%LotSize() != 0) )
       {
          ShowMessage("StartQ или Q не кратно лоту. Робот остановлен !");
          Stop();
       }
       // Продажа StartQ
       if (StartQ > 0)       
       {
         EnterShortLimit(Input1.Close[0]*(1.0 - 0.01*DeltaPercent), StartQ);
       }
         xPrice = Input1.Close[0];
    }
   
// Модуль проверки изменение позиции UP
   // если позиция выросла, добавляем уровень в список
   if (N > 0)
   {
      if ( pos > xPosition )   
      {     
           double a = xPrice;
           double b = xPosition;
                 
            while (pos - b > 0)
            {
               LastPrice.Add(a);
               a = a*(1.0 + 0.01*DeltaPercent);
               b = b + Q;
             }           
           Last = xPrice;
           xPosition = pos;             
           LastPrice.Sort();
      }
      // если позиция снизилась, убираем уровень из списка
      else if ( pos < xPosition && LastPrice.Count >= 1 )
      {
         LastPrice.Sort();
         LastPrice.RemoveAt(0);
         Last = xPrice;
         xPosition = pos;             
      }   
   
      if ( LastPrice.Count <= 0 )
          MinPrice = Last;
       else
          MinPrice = LastPrice.Min();
   }
   
// Модуль проверки изменение позиции DOWN
   // если позиция снизилась, добавляем уровень в список
   if (N < 0)
   {
      if ( pos < xPosition )   
      {     
           double a = xPrice;
           double b = xPosition;
                 
            while (pos - b < 0)
            {
               LastPrice.Add(a);
               a = a*(1.0 - 0.01*DeltaPercent);
               b = b - Q;
             }           
           Last = xPrice;
           xPosition = pos;             
           LastPrice.Sort();
           LastPrice.Reverse();
      }
      // если позиция выросла, убираем уровень из списка
      else if ( pos > xPosition && LastPrice.Count >= 1 )
      {
         LastPrice.Sort();
         LastPrice.Reverse();
         LastPrice.RemoveAt(0);
         Last = xPrice;
         xPosition = pos;             
      }   
   
      if ( LastPrice.Count <= 0 )
          MaxPrice = Last;
       else
          MaxPrice = LastPrice.Max();
   }
   
                       
//Правило 2. Если цена упала и кол-во меньше допустимого,
//           то покупаем и добавляем цену покупки в начало списка
   if ( N > 0 && Input1.Close[0] < MinPrice*(1.0 - 0.01*DeltaPercent) && pos + Q <= LongLimit )
   {
      EnterLongLimit(Input1.Close[0]*(1.0 + 0.5*0.01*DeltaPercent), Q);
        xPrice =  Input1.Close[0];
     }
//Правило 2.1. Если цена выросла и кол-во больше допустимого,
//           то продаем и добавляем цену продажи в начало списка
   if ( N < 0 && Input1.Close[0] > MaxPrice*(1.0 + 0.01*DeltaPercent) && pos - Q >= ShortLimit )
   {
      EnterShortLimit(Input1.Close[0]*(1.0 - 0.5*0.01*DeltaPercent), Q);
        xPrice =  Input1.Close[0];
     }     
//Правило 3. Если цена выше цены из начала списка, то продаем и удаляем 0-й элемент списка
   if ( N > 0 && Input1.Close[0] >= MinPrice*(1.0 + 0.01*DeltaPercent) && pos > 0 )
    {
       CloseLongLimit(Input1.Close[0]*(1.0 - 0.5*0.01*DeltaPercent), Q);
         xPrice =  Input1.Close[0];
     }
//Правило 3.1. Если цена ниже цены из начала списка, то покупаем и удаляем 0-й элемент списка
   if ( N < 0 && Input1.Close[0] <= MaxPrice*(1.0 - 0.01*DeltaPercent) && pos < 0 )
    {
       CloseShortLimit(Input1.Close[0]*(1.0 + 0.5*0.01*DeltaPercent), Q);
         xPrice =  Input1.Close[0];
     }
}
никогда такого не было и вот опять

Konstantin
Сообщения: 17
Зарегистрирован: 11 окт 2017, 15:25
Благодарил (а): 5 раз

Re: Усреднение!

Непрочитанное сообщение Konstantin » 06 авг 2020, 19:01

evge писал(а):вот что-то подобное

Код: Выделить всё

function Initialize()
{
   StrategyName = "UpAndDownMA";
   AddInput("Input1", Inputs.Candle, 5, true, "GAZP=МБ ЦК");
   AddParameter("StartQ", 1500, "Стартовое кол-во", 0);
   AddParameter("Q", 300, "Кол-во докупки", 0);
   AddParameter("DeltaPercent", 0.1, "% изменения цены для докупки и продажи", 0);
   AddParameter("SMAper", 99, "MA Period", 0);
           
   AddGlobalVariable("xPrice", Types.Double, 10000000000.0);
   AddGlobalVariable("xPosition", Types.Double, 0.0);
   AddGlobalVariable("LastPrice", Types.DoubleList);
   AddGlobalVariable("Last", Types.Double, 0);
   AddGlobalVariable("MinPrice", Types.Double, 0);
   AddGlobalVariable("MaxPrice", Types.Double, 99999999);   
   AddGlobalVariable("Type", Types.Double, 1);
   
   AddGlobalVariable("N", Types.Int, 1); //направление "1" - Long, "-1" - Short
   AddChartIndicator("SMA", new Dictionary <string, string>{{"Period", "SMAper"}});
}

function OnUpdate()
{

// evge 13.04.2019 https://alfadirect4.ru
// модификация стратегии StepByStep от AlfaDirect
// evge 06.08.2020 https://alfadirect4.ru
// работа по MA

var CP = CurrentPosition();

var sMA = SMA(Input1, SMAper);
var NN = sMA[0] > sMA[1] ? 1 : sMA[0] < sMA[1] ? - 1 : N;
if (N == 0) N = NN;

// Переворот при смене направления
if (N != NN && CP > 0 && NN < 0) { ClosePosition(); xPosition = 1; N = NN; CP = 0; return; }
if (N != NN && CP < 0 && NN > 0) { ClosePosition(); xPosition = -1; N = NN; CP = 0; return; }

if (xPosition !=0 && CP == 0)
{
   //N =- N;
   xPrice = 10000000000.0;
   LastPrice.Clear();
   xPosition = 0;
   MaxPrice = Double.MaxValue;
   MinPrice = 0;
}

double pos = CurrentPosition();
// Правило 1. если первый запуск, покупаем  StartQ
   if ( xPrice == 10000000000.0 && N > 0)
   {
       if ( (Q%LotSize() != 0) || (StartQ%LotSize() != 0) )
       {
          ShowMessage("StartQ или Q не кратно лоту. Робот остановлен !");
          Stop();
       }
       // Покупка StartQ
       if (StartQ > 0)       
       {
         EnterLongLimit(Input1.Close[0]*(1.0 + 0.01*DeltaPercent), StartQ);
       }
         xPrice = Input1.Close[0];
    }
// Правило 1.1 старт для Short, продаем StartQ
   if ( xPrice == 10000000000.0 && N < 0)
   {
       if ( (Q%LotSize() != 0) || (StartQ%LotSize() != 0) )
       {
          ShowMessage("StartQ или Q не кратно лоту. Робот остановлен !");
          Stop();
       }
       // Продажа StartQ
       if (StartQ > 0)       
       {
         EnterShortLimit(Input1.Close[0]*(1.0 - 0.01*DeltaPercent), StartQ);
       }
         xPrice = Input1.Close[0];
    }
   
// Модуль проверки изменение позиции UP
   // если позиция выросла, добавляем уровень в список
   if (N > 0)
   {
      if ( pos > xPosition )   
      {     
           double a = xPrice;
           double b = xPosition;
                 
            while (pos - b > 0)
            {
               LastPrice.Add(a);
               a = a*(1.0 + 0.01*DeltaPercent);
               b = b + Q;
             }           
           Last = xPrice;
           xPosition = pos;             
           LastPrice.Sort();
      }
      // если позиция снизилась, убираем уровень из списка
      else if ( pos < xPosition && LastPrice.Count >= 1 )
      {
         LastPrice.Sort();
         LastPrice.RemoveAt(0);
         Last = xPrice;
         xPosition = pos;             
      }   
   
      if ( LastPrice.Count <= 0 )
          MinPrice = Last;
       else
          MinPrice = LastPrice.Min();
   }
   
// Модуль проверки изменение позиции DOWN
   // если позиция снизилась, добавляем уровень в список
   if (N < 0)
   {
      if ( pos < xPosition )   
      {     
           double a = xPrice;
           double b = xPosition;
                 
            while (pos - b < 0)
            {
               LastPrice.Add(a);
               a = a*(1.0 - 0.01*DeltaPercent);
               b = b - Q;
             }           
           Last = xPrice;
           xPosition = pos;             
           LastPrice.Sort();
           LastPrice.Reverse();
      }
      // если позиция выросла, убираем уровень из списка
      else if ( pos > xPosition && LastPrice.Count >= 1 )
      {
         LastPrice.Sort();
         LastPrice.Reverse();
         LastPrice.RemoveAt(0);
         Last = xPrice;
         xPosition = pos;             
      }   
   
      if ( LastPrice.Count <= 0 )
          MaxPrice = Last;
       else
          MaxPrice = LastPrice.Max();
   }
   
                       
//Правило 2. Если цена упала и кол-во меньше допустимого,
//           то покупаем и добавляем цену покупки в начало списка
   if ( N > 0 && Input1.Close[0] < MinPrice*(1.0 - 0.01*DeltaPercent) && pos + Q <= LongLimit )
   {
      EnterLongLimit(Input1.Close[0]*(1.0 + 0.5*0.01*DeltaPercent), Q);
        xPrice =  Input1.Close[0];
     }
//Правило 2.1. Если цена выросла и кол-во больше допустимого,
//           то продаем и добавляем цену продажи в начало списка
   if ( N < 0 && Input1.Close[0] > MaxPrice*(1.0 + 0.01*DeltaPercent) && pos - Q >= ShortLimit )
   {
      EnterShortLimit(Input1.Close[0]*(1.0 - 0.5*0.01*DeltaPercent), Q);
        xPrice =  Input1.Close[0];
     }     
//Правило 3. Если цена выше цены из начала списка, то продаем и удаляем 0-й элемент списка
   if ( N > 0 && Input1.Close[0] >= MinPrice*(1.0 + 0.01*DeltaPercent) && pos > 0 )
    {
       CloseLongLimit(Input1.Close[0]*(1.0 - 0.5*0.01*DeltaPercent), Q);
         xPrice =  Input1.Close[0];
     }
//Правило 3.1. Если цена ниже цены из начала списка, то покупаем и удаляем 0-й элемент списка
   if ( N < 0 && Input1.Close[0] <= MaxPrice*(1.0 - 0.01*DeltaPercent) && pos < 0 )
    {
       CloseShortLimit(Input1.Close[0]*(1.0 + 0.5*0.01*DeltaPercent), Q);
         xPrice =  Input1.Close[0];
     }
}


Спасибо, всё работает отлично, но ещё лучше будет, если закрываться позиции будут при одновременном выполнении двух условий: показания МА о смене тренда и достижение уровня DeltaPercent. Это позволит избежать лишних открытий/закрытий во флэте.

Аватара пользователя
evge
Администратор
Сообщения: 1652
Зарегистрирован: 04 фев 2016, 09:46
Откуда: Млечный путь, планета Земля
Благодарил (а): 64 раза
Поблагодарили: 303 раза
Контактная информация:

Re: Усреднение!

Непрочитанное сообщение evge » 06 авг 2020, 19:18

Хорошо, ориентируясь на MinPrice и MaxPrice и отклонение цены от них на DeltaPercent

тогда вот так:

Код: Выделить всё

function Initialize()
{
   StrategyName = "UpAndDownMA";
   AddInput("Input1", Inputs.Candle, 5, true, "GAZP=МБ ЦК");
   AddParameter("StartQ", 500, "Стартовое кол-во", 0);
   AddParameter("Q", 100, "Кол-во докупки", 0);
   AddParameter("DeltaPercent", 0.4, "% изменения цены для докупки и продажи", 0);
   AddParameter("SMAper", 99, "MA Period", 0);
           
   AddGlobalVariable("xPrice", Types.Double, 10000000000.0);
   AddGlobalVariable("xPosition", Types.Double, 0.0);
   AddGlobalVariable("LastPrice", Types.DoubleList);
   AddGlobalVariable("Last", Types.Double, 0);
   AddGlobalVariable("MinPrice", Types.Double, 0);
   AddGlobalVariable("MaxPrice", Types.Double, 99999999);   
   AddGlobalVariable("Type", Types.Double, 1);
   
   AddGlobalVariable("N", Types.Int, 1); //направление "1" - Long, "-1" - Short
   AddChartIndicator("SMA", new Dictionary <string, string>{{"Period", "SMAper"}});
}

function OnUpdate()
{

// evge 13.04.2019 https://alfadirect4.ru
// модификация стратегии StepByStep от AlfaDirect
// evge 06.08.2020 https://alfadirect4.ru
// работа по MA + DeltaPercent от MinPrice и MaxPrice

var CP = CurrentPosition();

var sMA = SMA(Input1, SMAper);
var NN = sMA[0] > sMA[1] && Input1.Close[0] > MaxPrice*(1.0 + 0.01*DeltaPercent) ? 1 : sMA[0] < sMA[1] && Input1.Close[0] < MinPrice*(1.0 + 0.01*DeltaPercent) ? - 1 : N;
if (N == 0) N = NN;

// Переворот при смене направления
if (N != NN && CP > 0 && NN < 0) { ClosePosition(); xPosition = 1; N = NN; CP = 0; return; }
if (N != NN && CP < 0 && NN > 0) { ClosePosition(); xPosition = -1; N = NN; CP = 0; return; }

if (xPosition !=0 && CP == 0)
{
   //N =- N;
   xPrice = 10000000000.0;
   LastPrice.Clear();
   xPosition = 0;
   MaxPrice = Double.MaxValue;
   MinPrice = 0;
}

double pos = CurrentPosition();
// Правило 1. если первый запуск, покупаем  StartQ
   if ( xPrice == 10000000000.0 && N > 0)
   {
       if ( (Q%LotSize() != 0) || (StartQ%LotSize() != 0) )
       {
          ShowMessage("StartQ или Q не кратно лоту. Робот остановлен !");
          Stop();
       }
       // Покупка StartQ
       if (StartQ > 0)       
       {
         EnterLongLimit(Input1.Close[0]*(1.0 + 0.01*DeltaPercent), StartQ);
       }
         xPrice = Input1.Close[0];
    }
// Правило 1.1 старт для Short, продаем StartQ
   if ( xPrice == 10000000000.0 && N < 0)
   {
       if ( (Q%LotSize() != 0) || (StartQ%LotSize() != 0) )
       {
          ShowMessage("StartQ или Q не кратно лоту. Робот остановлен !");
          Stop();
       }
       // Продажа StartQ
       if (StartQ > 0)       
       {
         EnterShortLimit(Input1.Close[0]*(1.0 - 0.01*DeltaPercent), StartQ);
       }
         xPrice = Input1.Close[0];
    }
   
// Модуль проверки изменение позиции UP
   // если позиция выросла, добавляем уровень в список
   if (N > 0)
   {
      if ( pos > xPosition )   
      {     
           double a = xPrice;
           double b = xPosition;
                 
            while (pos - b > 0)
            {
               LastPrice.Add(a);
               a = a*(1.0 + 0.01*DeltaPercent);
               b = b + Q;
             }           
           Last = xPrice;
           xPosition = pos;             
           LastPrice.Sort();
      }
      // если позиция снизилась, убираем уровень из списка
      else if ( pos < xPosition && LastPrice.Count >= 1 )
      {
         LastPrice.Sort();
         LastPrice.RemoveAt(0);
         Last = xPrice;
         xPosition = pos;             
      }   
   
      if ( LastPrice.Count <= 0 )
          MinPrice = Last;
       else
          MinPrice = LastPrice.Min();
   }
   
// Модуль проверки изменение позиции DOWN
   // если позиция снизилась, добавляем уровень в список
   if (N < 0)
   {
      if ( pos < xPosition )   
      {     
           double a = xPrice;
           double b = xPosition;
                 
            while (pos - b < 0)
            {
               LastPrice.Add(a);
               a = a*(1.0 - 0.01*DeltaPercent);
               b = b - Q;
             }           
           Last = xPrice;
           xPosition = pos;             
           LastPrice.Sort();
           LastPrice.Reverse();
      }
      // если позиция выросла, убираем уровень из списка
      else if ( pos > xPosition && LastPrice.Count >= 1 )
      {
         LastPrice.Sort();
         LastPrice.Reverse();
         LastPrice.RemoveAt(0);
         Last = xPrice;
         xPosition = pos;             
      }   
   
      if ( LastPrice.Count <= 0 )
          MaxPrice = Last;
       else
          MaxPrice = LastPrice.Max();
   }
   
                       
//Правило 2. Если цена упала и кол-во меньше допустимого,
//           то покупаем и добавляем цену покупки в начало списка
   if ( N > 0 && Input1.Close[0] < MinPrice*(1.0 - 0.01*DeltaPercent) && pos + Q <= LongLimit )
   {
      EnterLongLimit(Input1.Close[0]*(1.0 + 0.5*0.01*DeltaPercent), Q);
        xPrice =  Input1.Close[0];
     }
//Правило 2.1. Если цена выросла и кол-во больше допустимого,
//           то продаем и добавляем цену продажи в начало списка
   if ( N < 0 && Input1.Close[0] > MaxPrice*(1.0 + 0.01*DeltaPercent) && pos - Q >= ShortLimit )
   {
      EnterShortLimit(Input1.Close[0]*(1.0 - 0.5*0.01*DeltaPercent), Q);
        xPrice =  Input1.Close[0];
     }     
//Правило 3. Если цена выше цены из начала списка, то продаем и удаляем 0-й элемент списка
   if ( N > 0 && Input1.Close[0] >= MinPrice*(1.0 + 0.01*DeltaPercent) && pos > 0 )
    {
       CloseLongLimit(Input1.Close[0]*(1.0 - 0.5*0.01*DeltaPercent), Q);
         xPrice =  Input1.Close[0];
     }
//Правило 3.1. Если цена ниже цены из начала списка, то покупаем и удаляем 0-й элемент списка
   if ( N < 0 && Input1.Close[0] <= MaxPrice*(1.0 - 0.01*DeltaPercent) && pos < 0 )
    {
       CloseShortLimit(Input1.Close[0]*(1.0 + 0.5*0.01*DeltaPercent), Q);
         xPrice =  Input1.Close[0];
     }
}
никогда такого не было и вот опять

Аватара пользователя
evge
Администратор
Сообщения: 1652
Зарегистрирован: 04 фев 2016, 09:46
Откуда: Млечный путь, планета Земля
Благодарил (а): 64 раза
Поблагодарили: 303 раза
Контактная информация:

Re: Усреднение!

Непрочитанное сообщение evge » 06 авг 2020, 19:30

но есть вероятность что не перевернется, если цена дальше уйдёт в том же направлении

при тестах это вижу

нужно наверное ориентир другой, не MinPrice и MaxPrice

пример, с января по август 2020, GAZP

с марта и далее уже цена не была выше 210 и переворота не случилось

UoAndDoownMA-02.png
UoAndDoownMA-02.png (46.86 КБ) 1985 просмотров

UoAndDoownMA-01.png
UoAndDoownMA-01.png (22.94 КБ) 1986 просмотров
никогда такого не было и вот опять


Вернуться в «Стратегии и роботы»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 11 гостей