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

Обсуждение, описание стратегий и роботов, идеи для стратегий
Konstantin
Сообщения: 20
Зарегистрирован: 11 окт 2017, 15:25
Благодарил (а): 6 раз

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

Непрочитанное сообщение Konstantin » 07 авг 2020, 13:40

evge писал(а):Код который выше, он полностью как у меня.

Спасибо! Буду разбираться, я бы такую головоломку целый месяц решал и код был бы в несколько раз длиннее :)

Максим
Сообщения: 16
Зарегистрирован: 07 апр 2019, 11:01
Благодарил (а): 14 раз

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

Непрочитанное сообщение Максим » 02 дек 2020, 13:55

Здравствуйте. Есть простая стратегия для флета (см ниже), робот открывает позиции в зонах экстремальных значений SO (ниже 20 - лонг, выше 80 - шорт), и выставляет TP и SL = 100.
Хотелось бы, чтобы при смещении цены против открытой позиции на 50, робот открывал дополнительную позицию такого же объема, SL=50, TP=100, а TP предыдущей позиции смещал на цену открытия+1 (пункт). Например, зашли в лонг по 2100, объемом 10 лотов, TP1=2200, SL1=2000. Цена уходит до 2050. Открывается еще одна позиция, объемом 10 лотов, TP2=2150, SL2=2000, а TP1 переставляется на 2101. Как это корректно сделать?
Спасибо!

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

/**
Вход на экстремумах стохастика во флете. Ниже 20 - лонг, выше 80 - шорт.
**/
function Initialize()
{
   StrategyName = "15_Stoch";
   AddParameter("P3", 20, "Экстремум минимальный стохастик", 1);
   AddParameter("P4", 80, "Экстремум максимальный стохастик", 1);
   AddParameter("P5", 35, "K%", 1);
   AddParameter("P6", 3, "D%", 1);
   AddParameter("P7", 7, "Стохастик Сигнал", 1);
   AddParameter("P8", 100, "Тейк профит", 1);
   AddParameter("P9", 100, "Стоп лосс", 1);
   AddInput("Input1", Inputs.Candle, 15, true, "");
   LongLimit = 1;
   ShortLimit = -1;
   AddChartIndicator("Stoch", new Dictionary <string, string>{{"PeriodK", "P5"},{"PeriodD", "P6"},{"PeriodSignal", "P7"}});
}

function OnUpdate()
{
   /// ПРАВИЛО 1
   if ( (SO(Input1, P5, P6, P7).GetValue("Signal", 0) < P3) )
   {
      EnterLong();
      BreakingStop(P9, P8, SignalPriceType.DeltaFromAveragePrice);

   }

   /// ПРАВИЛО 2
   if ( (SO(Input1, P5, P6, P7).GetValue("Signal", 0) > P4) )
   {
      EnterShort();
      BreakingStop(P9, P8, SignalPriceType.DeltaFromAveragePrice);

   }

}

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

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

Непрочитанное сообщение evge » 02 дек 2020, 15:29

Позиция по роботу одна. Стоп и тейк тоже один. Одновременно 2 позиции можно вести только храня в глоб. переменных эти данные. Но закрывать точно по стопу и тейку не получится, только в момент OnUpdate, т.е. на следующем баре за текущим. Закрывать без установки реальных стопов и тейков, ориентируясь на глоб. переменные ранее открытых и сохраненных позиций и текущую цену (OHLC).
никогда такого не было и вот опять

Максим
Сообщения: 16
Зарегистрирован: 07 апр 2019, 11:01
Благодарил (а): 14 раз

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

Непрочитанное сообщение Максим » 02 дек 2020, 16:30

То есть, только двумя роботами можно подобное реализовать?

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

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

Непрочитанное сообщение evge » 02 дек 2020, 17:33

Второй робот не видит позиции первого. Реализовать можно, как описал выше, но с ограничениями описанными по поводу срабатывания на эти позиции стопов и тейков. Закрываться позиции будут на закрытиях бара (правильнее на первом тике следующего бара), т.е. при наступлении события OnUpdate(), где мы смотрим текущую цену и сравниваем с позициями хранимыми в глобальных переменных робота и принимаем решение на основании отклонения от этих позиций.
никогда такого не было и вот опять

Orange2000
Сообщения: 47
Зарегистрирован: 13 мар 2019, 00:45
Благодарил (а): 37 раз
Поблагодарили: 1 раз

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

Непрочитанное сообщение Orange2000 » 19 апр 2021, 10:37

► Показать

Евгений приветствую.
Прогнал код (от 18 апреля 20 г) из этого сообщения на СИ за месяц последний. Почему-то в некоторые дни , например 16апреля, входит в лонг утром и только вечером закрывает, не делая внутри дня сделок.

sim1, 1 минута,
Параметры : 1/1/0,15

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

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

Непрочитанное сообщение evge » 19 апр 2021, 15:54

Orange2000 писал(а):...Почему-то в некоторые дни , например 16апреля, входит в лонг утром и только вечером закрывает, не делая внутри дня сделок...


Приветствую!

Задайте предельную позицию Long, Short при тестировании вместо 1 что-то большее, для того чтобы тестер смог докупать.

UpAndDownCP-02.png
UpAndDownCP-02.png (30 КБ) 16830 просмотров


итог (было \ стало)

UpAndDownCP-01.png
никогда такого не было и вот опять

Orange2000
Сообщения: 47
Зарегистрирован: 13 мар 2019, 00:45
Благодарил (а): 37 раз
Поблагодарили: 1 раз

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

Непрочитанное сообщение Orange2000 » 19 апр 2021, 18:35

Евгений, спасибо) Тупанул..забыл про эту фишку с предельной позицией))

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

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

Непрочитанное сообщение Konstantin » 16 сен 2021, 22:52

Евгений, у меня появилась идея, как можно сделать стратегию более гибкой, для этого нужно привязать параметр DeltaPercent к показаниям второго индикатора МА.
Если показания второго индикатора МА_2 противоречат первому индикатору МА_1, и период МА_2 больше МА_1, то DeltaPercent увеличивается, например, на 20%, а если период МА_2 меньше МА_1, то DeltaPercent уменьшается на 20%.
Поможете с кодом?

Последняя удачная версия:

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

function Initialize()
{
   StrategyName = "UpAndDownMA";
   AddInput("Input1", Inputs.Candle, 30, true, "GAZP=МБ ЦК");
   AddParameter("StartQ", 290, "Стартовое кол-во", 0);
   AddParameter("Q", 10, "Кол-во докупки", 0);
   AddParameter("DeltaPercent", 0.6, "% изменения цены для докупки и продажи", 0);
   AddParameter("SMAper", 95, "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
Администратор
Сообщения: 1811
Зарегистрирован: 04 фев 2016, 09:46
Откуда: Млечный путь, планета Земля
Благодарил (а): 83 раза
Поблагодарили: 367 раз
Контактная информация:

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

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

Если по описанным условиям, то так (но результат работы не проверял):

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

function Initialize()
{
   StrategyName = "UpAndDownMA2";
   AddInput("Input1", Inputs.Candle, 30, true, "GAZP=МБ ЦК");
   AddParameter("StartQ", 290, "Стартовое кол-во", 0);
   AddParameter("Q", 10, "Кол-во докупки", 0);
   AddParameter("DeltaPercent", 0.6, "% изменения цены для докупки и продажи", 0);
   AddParameter("SMAper", 95, "MA Period", 0);
   AddParameter("SMAper2", 55, "MA Period", 0);
   AddParameter("DPAdd", 0.2, "Доп увеличение или уменьшение для DeltaPercent", 0); 
   //Если сигналы по SMA1 и SMA2 противоречат друг другу, то
   //Если SMAper2 > SMAper, тогда DeltaPercent увеличивается на DPAdd
   //Если SMAper2 < SMAper, тогда DeltaPercent уменьшается на DPAdd
           
   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"}});
   AddChartIndicator("SMA", new Dictionary <string, string>{{"Period", "SMAper2"}});
}

function OnUpdate()
{

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

var CP = CurrentPosition();

var sMA = SMA(Input1, SMAper);
var sMA2 = SMA(Input1, SMAper2);

double DP = DeltaPercent;

if ((sMA2[0] > sMA2[1] && sMA[0] < sMA[1]) || (sMA2[0] < sMA2[1] && sMA[0] > sMA[1]))
if (SMAper2 > SMAper) DP += DPAdd; else if (SMAper2 < SMAper) DP -= DPAdd;

var NN = sMA[0] > sMA[1] && Input1.Close[0] > MaxPrice*(1.0 + 0.01*DP) ? 1 : sMA[0] < sMA[1] && Input1.Close[0] < MinPrice*(1.0 + 0.01*DP) ? - 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*DP), 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*DP), 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*DP);
               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*DP);
               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*DP) && pos + Q <= LongLimit )
   {
      EnterLongLimit(Input1.Close[0]*(1.0 + 0.5*0.01*DP), Q);
        xPrice =  Input1.Close[0];
     }
//Правило 2.1. Если цена выросла и кол-во больше допустимого,
//           то продаем и добавляем цену продажи в начало списка
   if ( N < 0 && Input1.Close[0] > MaxPrice*(1.0 + 0.01*DP) && pos - Q >= ShortLimit )
   {
      EnterShortLimit(Input1.Close[0]*(1.0 - 0.5*0.01*DP), Q);
        xPrice =  Input1.Close[0];
     }     
//Правило 3. Если цена выше цены из начала списка, то продаем и удаляем 0-й элемент списка
   if ( N > 0 && Input1.Close[0] >= MinPrice*(1.0 + 0.01*DP) && pos > 0 )
    {
       CloseLongLimit(Input1.Close[0]*(1.0 - 0.5*0.01*DP), Q);
         xPrice =  Input1.Close[0];
     }
//Правило 3.1. Если цена ниже цены из начала списка, то покупаем и удаляем 0-й элемент списка
   if ( N < 0 && Input1.Close[0] <= MaxPrice*(1.0 - 0.01*DP) && pos < 0 )
    {
       CloseShortLimit(Input1.Close[0]*(1.0 + 0.5*0.01*DP), Q);
         xPrice =  Input1.Close[0];
     }
}
никогда такого не было и вот опять


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

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

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