Разработка трендовых стратегий - помощь в реализации / сотрудничество - страница 2

 
Renat Akhtyamov #:

математически будет, на практике и в тестере - нет

Можете проверить:

Настройки тестирования и входные параметры

Настройки тестирования:

Настройки тестирования советника Moving Average

Параметры тестирования без фильтров:

Параметры тестирования советника Moving Average без фильтров

Параметры тестирования с фильтром закрытия сделок L1 Close Filter:

Параметры тестирования советника Moving Average с фильтром закрытия сделок L1 Close Filter

Результаты тестирования:

Стратегия без фильтров:

Результаты тестирования советника Moving Average без фильтров

Стратегия с фильтром закрытия L1 Close Filter:

Результаты тестирования советника Moving Average с фильтром закрытия сделок L1 Close Filter

Файлы:
 

Ранее были показаны результаты с наилучшими параметрами для MovingAverage.

Результаты для других трендовых стратегий (MACD, ADX, EMA)

1. MACD

Настройки тестирования и входные параметры

Настройки тестирования:

MACD Test options

Параметры тестирования без фильтров:

Параметры тестирования советника MACD без фильтров

Параметры тестирования с фильтром закрытия сделок L1 Close Filter:

Параметры тестирования советника MACD с фильтром закрытия сделок L1 Close Filter

Результаты тестирования:

Стратегия без фильтров:

Результаты тестирования совеника MACD без фильтров

Стратегия с фильтром закрытия L1 Close Filter:

Результаты тестирования совеника MACD с фильтром закрытия сделок L1 Close Filter


2. ADX

Настройки тестирования и входные параметры

Настройки тестирования:

Настройки тестирования советника ADX

Параметры тестирования без фильтров:

Параметры тестирования советника ADX без фильтров

Параметры тестирования с фильтром закрытия сделок L1 Close Filter:

Параметры тестирования советника ADX с фильтром закрытия сделок L1 Close Filter

Результаты тестирования:

Стратегия без фильтров:

Результаты тестирования советника ADX без фильтров

Стратегия с фильтром закрытия L1 Close Filter:

Результаты тестирования советника ADX с фильтром закрытия сделок L1 Close Filter


3. EMA

Настройки тестирования и входные параметры

Настройки тестирования:

Настройки тестирования

Параметры тестирования без фильтров:

Параметры тестирования без фильтров

Параметры тестирования с фильтром закрытия сделок L1 Close Filter:

Параметры тестирования с фильтром закрытия сделок L1 Close Filter

Результаты тестирования:

Стратегия без фильтров:

Результаты тестирования советника по стратегии EMA без фильтров

Стратегия с фильтром закрытия L1 Close Filter:

Результаты тестирования советника по стратегии EMA с фильтром закрытия сделок L1 Close Filter

Файлы:
 

Индикаторы тренда на базе L1 Trend Filter

Индикаторы тренда на базе L1 Trend Filter


Индикаторы тренда на базе L1 Trend Filter

L1-фильтр тренда может быть использован для разметки данных при использовании машинного обучения. В частности, в статье "Разработка трендовых торговых стратегий на основе машинного обучения"  для определения тренда используются производные цен, сглаженных фильтром Савицкого–Голея.

Аналогичный подход может быть реализован с помощью L1-фильтрации, где тренд аппроксимируется кусочно-линейными функциями, а сила тренда на каждом участке естественным образом связана с наклоном соответствующего сегмента. Режимы тренда, определяемые через индикаторы волатильности, также могут быть использованы в качестве признаков ML-разметки торговых сигналов.

 

Разность между ценой и трендом позволяет точнее оценить волатильность и ранжировать ее режимы.

Индикаторы волатильности на базе L1-тренда

Эти инструменты дают возможность выявлять периоды нестабильности и устойчивости рынка, анализировать текущую динамику и принимать более обоснованные торговые решения.

Описание индиакторов волатильности:

  • L1Volatility.mq5 – расчет остаточной волатильности по L1-тренду;
  • L1VolatilitySmoothed.mq5 – сглаженная остаточная волатильность;
  • L1VolatilityAbsolute.mq5 – абсолютная волатильность;
  • L1VolatilityNormalized.mq5 – нормализованная волатильность;
  • L1VolatilityNormalizedSmoothed.mq5 – сглаженная нормализованная волатильность;
  • L1VolatilityRegime.mq5 – определение режима рынка по волатильности.
  • L1VolatilityRegimeColor.mq5 – цветная версия индиактора режима рынка по волатильности.

Эти индикаторы основаны на едином подходе L1-тренда, что обеспечивает согласованность анализа и упрощает интерпретацию получаемых данных.

Использование этих индикаторов позволяет визуально выделять периоды высокой и низкой волатильности, а также определять текущий рыночный режим — флет, тренд, расширение или панику.

Благодаря этому трейдер может адаптировать торговую стратегию под актуальные рыночные условия, например, выбирать более консервативные подходы во время низкой волатильности или активные стратегии при сильных движениях рынка.

Индикаторы волатильности на базе L1-тренда

 

Пример применения L1-фильтра для удаления шума в изображениях

ℓ1 Trend Filter for Image Denoising (2016) Procedia Computer Science 93:495-502

Основная проблема цифровой обработки изображений заключается в наличии нежелательных частот (шума).
В данной работе ℓ1-trend фильтр предлагается как метод подавления шума в изображениях. ℓ1-trend фильтр оценивает скрытый тренд в данных, формулируя задачу выпуклой оптимизации на основе ℓ1-нормы.
Предложенный метод расширяет применение ℓ1-trend фильтра с одномерных сигналов на трёхмерные цветные изображения.
Здесь фильтр применяется к изображению каскадным образом: сначала выполняется фильтрация вдоль строк, затем — вдоль столбцов.
Это позволяет выявить скрытую информацию изображения из зашумлённого изображения, что приводит к получению сглаженного (очищенного от шума) изображения.
Предложенный метод сравнивается с методом шумоподавления на основе вейвлетов с использованием метрик качества:

  • Peak Signal-to-Noise Ratio (PSNR) — пиковое отношение сигнал/шум,
  • Structural Similarity Index (SSIM) — индекс структурного сходства.

Код:

//+------------------------------------------------------------------+
//|                                               L1ImageDenoise.mq5 |
//|                             Copyright 2000-2026, MetaQuotes Ltd. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2026, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#include <Canvas\Canvas.mqh>
#include <Graphics\Graphic.mqh>

uint32_t ExtSeed = 1;
//+------------------------------------------------------------------+
//| Convert BMP image to double vectors RGB                          |
//+------------------------------------------------------------------+
bool PreprocessImage(vector<double> &red, vector<double> &green, vector<double> &blue, uint &image_data[], int width, int height)
  {
   red.Resize(width*height);
   green.Resize(width*height);
   blue.Resize(width*height);

   for(int y=0; y<height; y++)
      for(int x=0; x<width; x++)
        {
         int offset = y*width + x;
         uint clr = image_data[offset];
         red[offset]   = double((clr>>16)&0xFF)/255.0;
         green[offset] = double((clr>>8)&0xFF)/255.0;
         blue[offset]  = double(clr&0xFF)/255.0;
        }
   return true;
  }
//+------------------------------------------------------------------+
//| Clamp value to range                                             |
//+------------------------------------------------------------------+
double clamp(double value, double minValue, double maxValue)
  {
   return MathMin(MathMax(value, minValue), maxValue);
  }
//+------------------------------------------------------------------+
//| Convert double vectors back to image                             |
//+------------------------------------------------------------------+
bool PostprocessImage(const vector<double> &red, const vector<double> &green, const vector<double> &blue, uint &image_data[], int width, int height)
  {
   ArrayResize(image_data, width*height);

   for(int y=0; y<height; y++)
      for(int x=0; x<width; x++)
        {
         int offset = y*width + x;
         uchar r = uchar(clamp(red[offset]*255.0,0,255));
         uchar g = uchar(clamp(green[offset]*255.0,0,255));
         uchar b = uchar(clamp(blue[offset]*255.0,0,255));
         image_data[offset] = XRGB(r,g,b);
        }
   return true;
  }
//+------------------------------------------------------------------+
//| L1 Trend Filter for single channel using vector<double>          |
//+------------------------------------------------------------------+
bool L1FilterChannel(vector<double> &channel, int width, int height, double lambda)
  {
   vector<double> row;
   row.Resize(width);
//--- по строкам
   for(int y=0; y<height; y++)
     {
      for(int x=0; x<width; x++)
         row[x] = channel[y*width + x];
      row.L1TrendFilter(lambda, true,row);
      for(int x=0; x<width; x++)
         channel[y*width + x] = row[x];
     }
   vector<double> col;
   col.Resize(height);
//--- по столбцам
   for(int x=0; x<width; x++)
     {
      for(int y=0; y<height; y++)
         col[y] = channel[y*width + x];
      col.L1TrendFilter(lambda,true,col);
      for(int y=0; y<height; y++)
         channel[y*width + x] = col[y];
     }
//---
   return true;
  }
//+------------------------------------------------------------------+
//| Show image on canvas                                             |
//+------------------------------------------------------------------+
bool ShowImage(CCanvas &canvas, string name, int x0, int y0, int width, int height, uint &image_data[])
  {
   canvas.CreateBitmapLabel(name, x0, y0, width, height, COLOR_FORMAT_XRGB_NOALPHA);
   for(int y=0; y<height; y++)
      for(int x=0; x<width; x++)
         canvas.PixelSet(x, y, image_data[y*width + x]);
   canvas.Update(true);
   return true;
  }
//+------------------------------------------------------------------+
//| Script start                                                     |
//+------------------------------------------------------------------+
void OnStart()
  {
   string image_path[1];

   if(FileSelectDialog("Select BMP image", NULL, "Bitmap files (*.bmp)|*.bmp", FSD_FILE_MUST_EXIST, image_path, "lenna.bmp") != 1)
     {
      Print("File not selected");
      return;
     }
//--- load BMP into array
   uint image_data[];
   int width, height;

   if(!CCanvas::LoadBitmap(image_path[0], image_data, width, height))
     {
      PrintFormat("CCanvas::LoadBitmap failed with error %d", GetLastError());
      return;
     }
//--- подготовка каналов
   vector<double> red, green, blue;
   PreprocessImage(red, green, blue, image_data, width, height);
//--- создаём 4 фильтрованных варианта
   double lambda_factors[4] = {0.00001, 0.00005, 0.0001, 0.0002};
   vector<double> red_f[4], green_f[4], blue_f[4];
   for(int i=0; i<4; i++)
     {
      red_f[i]   = red;
      green_f[i] = green;
      blue_f[i]  = blue;

      L1FilterChannel(red_f[i], width, height, lambda_factors[i]);
      L1FilterChannel(green_f[i], width, height, lambda_factors[i]);
      L1FilterChannel(blue_f[i], width, height, lambda_factors[i]);
     }
//--- постобработка
   uint filtered_data1[];
   uint filtered_data2[];
   uint filtered_data3[];
   uint filtered_data4[];
//---
   PostprocessImage(red_f[0], green_f[0], blue_f[0], filtered_data1, width, height);
   PostprocessImage(red_f[1], green_f[1], blue_f[1], filtered_data2, width, height);
   PostprocessImage(red_f[2], green_f[2], blue_f[2], filtered_data3, width, height);
   PostprocessImage(red_f[3], green_f[3], blue_f[3], filtered_data4, width, height);
//--- показать все 5 картинки рядом: оригинал + 4 варианта
   CCanvas canvas;
   canvas.CreateBitmapLabel("Comparison", 0, 0, width*5, height, COLOR_FORMAT_XRGB_NOALPHA);
//--- левый блок — оригинал
   for(int y=0; y<height; y++)
      for(int x=0; x<width; x++)
         canvas.PixelSet(x, y, image_data[y*width + x]);
//--- 4 фильтрованных блока
   int i=0;
   for(int y=0; y<height; y++)
      for(int x=0; x<width; x++)
         canvas.PixelSet(x + width*(i+1), y, filtered_data1[y*width + x]);
   i=1;
   for(int y=0; y<height; y++)
      for(int x=0; x<width; x++)
         canvas.PixelSet(x + width*(i+1), y, filtered_data2[y*width + x]);
   i=2;
   for(int y=0; y<height; y++)
      for(int x=0; x<width; x++)
         canvas.PixelSet(x + width*(i+1), y, filtered_data3[y*width + x]);
   i=3;
   for(int y=0; y<height; y++)
      for(int x=0; x<width; x++)
         canvas.PixelSet(x + width*(i+1), y, filtered_data4[y*width + x]);
//---
   canvas.Update(true);
   DebugBreak();
  }
//+------------------------------------------------------------------+

Different noises added into the Lenna image. 
a) Lenna image, 
b) Gaussian noise with σ = 0.05, 
c) salt and pepper noise with σ = 0.05, 
d) speckle noise with σ = 0.05, 
e) Poisson noise
f) periodic noise with amplitude A = 60, angular frequency ω = 30

Результат:

вариант a - оригинал

вариант b

вариант c

вариант d

вариант e

вариант f

(PDF) ℓ1 Trend Filter for Image Denoising
(PDF) ℓ1 Trend Filter for Image Denoising
  • www.researchgate.net
PDF | The major problem in digital image processing is the presence of unwanted frequencies(noise). In this paper ℓ1 trend filter is proposed as an... | Find, read and cite all the research you need on ResearchGate
Файлы:
 
Quantum #:

Разность между ценой и трендом позволяет точнее оценить волатильность и ранжировать ее режимы.

Индикаторы волатильности на базе L1-тренда

Эти инструменты дают возможность выявлять периоды нестабильности и устойчивости рынка, анализировать текущую динамику и принимать более обоснованные торговые решения.

Описание индиакторов волатильности:

  • L1Volatility.mq5 – расчет остаточной волатильности по L1-тренду;
  • L1VolatilitySmoothed.mq5 – сглаженная остаточная волатильность;
  • L1VolatilityAbsolute.mq5 – абсолютная волатильность;
  • L1VolatilityNormalized.mq5 – нормализованная волатильность;
  • L1VolatilityNormalizedSmoothed.mq5 – сглаженная нормализованная волатильность;
  • L1VolatilityRegime.mq5 – определение режима рынка по волатильности.
  • L1VolatilityRegimeColor.mq5 – цветная версия индиактора режима рынка по волатильности.

Эти индикаторы основаны на едином подходе L1-тренда, что обеспечивает согласованность анализа и упрощает интерпретацию получаемых данных.

Использование этих индикаторов позволяет визуально выделять периоды высокой и низкой волатильности, а также определять текущий рыночный режим — флет, тренд, расширение или панику.

Благодаря этому трейдер может адаптировать торговую стратегию под актуальные рыночные условия, например, выбирать более консервативные подходы во время низкой волатильности или активные стратегии при сильных движениях рынка.


И как эту логику можно использовать применительно с ледующей стратегии:

1. Берем трендовый актив (напр, XAU или BTC)
2. Работаем в лонг, открываем позиции по тренду после закрытия свечи при соблюдении условий фильтров (тф от Н2 до Н4) 
3. 1 и 2 позиции - сниженный риск в %, как "тест тренда" - то есть анализ рыночного состояния по закрытию свечи - "вход разрешен" - заходим 
4. тренд наше все, поэтому далее добираем позиции по тренду (3,4,5...) - анализ рыночного остояния "тренд продолжается" - добираем
* если ловим стоп-лосс в процессе набора, но признаки тренда сохраняются, нет условий для фиксации позиций - возможно, добор на откатах / восстановлении (пуллбэк) - особенно в рамках локальных проторговок
5. набрали позиции, большая часть в безубытке, рынок уходит в боковик - возрастают признаки фиксации - анализ рыночного состояния "тренд затухает" - начинаем частичную фиксацию позиций - по 1 штуке
6. Рынок переходит или в боковик, или в снижение, или тренд продолжается.
 
ivanov86 #:
И как эту логику можно использовать применительно с ледующей стратегии:

1. Берем трендовый актив (напр, XAU или BTC)
2. Работаем в лонг, открываем позиции по тренду после закрытия свечи при соблюдении условий фильтров (тф от Н2 до Н4) 
3. 1 и 2 позиции - сниженный риск в %, как "тест тренда" - то есть анализ рыночного состояния по закрытию свечи - "вход разрешен" - заходим 
4. тренд наше все, поэтому далее добираем позиции по тренду (3,4,5...) - анализ рыночного остояния "тренд продолжается" - добираем
* если ловим стоп-лосс в процессе набора, но признаки тренда сохраняются, нет условий для фиксации позиций - возможно, добор на откатах / восстановлении (пуллбэк) - особенно в рамках локальных проторговок
5. набрали позиции, большая часть в безубытке, рынок уходит в боковик - возрастают признаки фиксации - анализ рыночного состояния "тренд затухает" - начинаем частичную фиксацию позиций - по 1 штуке
6. Рынок переходит или в боковик, или в снижение, или тренд продолжается.

Конкретная реализация данной стратегии требует детального анализа (возможно с языковыми моделями).

В примерах #11 и #12  добор позиций на откатах не рассматривался, советник просто игнорирует ложные сигналы выхода от коррекций и таким образом "дает прибыли течь". В целом, именно таким образом (как фильтр выходов) L1-тренд может быть эффективен на трендовых рынках для подобных трендовых стратегий (как самостоятельный сигнал для входов он не годится, т.к. запаздывает), также он не дает уходить в сильные просадки (характер кривой в тестере).

 

Вариант советника MovingAverage с L1-фильтром выходов и с добавлением на коррекциях

Настройки тестирования и входные параметры

Настройки тестирования:

Параметры тестирования

1. Входные параметры для тестирования без фильтров:

Входные параметры для тестирования без фильтров

Результат:

Результат без фильтров

2. Входные параметры тестирования с L1-фильтром выходов и добавлением на коррекциях

Входные параметры тестирования с L1-фильтром выходов и добавлением

Результат с L1-фильтром выходов и добавлением на коррекциях:

Результат с L1-фильтром выходов и добавлением на коррекциях

Файлы:
 
ivanov86:

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

Пробойные стратегии более быстрые, поэтому результаты с L1-фильтром могут быть менее эффективными, чем для рассмотренных ранее трендовых стратегий на медленных скользящих средних.

Стратегия ATRChannelBreakout

Настройки тестирования:

Настройки тестирования советника ATR

1. Входные параметры без фильтров:

Входные параметры советника ATRChannelBreakoutFiltered без L1-фильтров

Результаты советника ATRChannelBreakoutFiltered без L1-фильтров

Результаты советника ATRChannelBreakoutFiltered без L1-фильтров

2. Входные параметры советника ATRChannelBreakoutFiltered с L1-фильтром выхода из рынка:

Входные параметры советника ATRChannelBreakoutFiltered с L1-фильтром выхода из рынка

Результаты советника ATRChannelBreakoutFiltered с L1-фильтром выхода из рынка:

Результаты советника ATRChannelBreakoutFiltered с L1-фильтром выхода из рынка:

Таким образом, в данном случае L1-фильтр выхода не смог улучшить прибыль (но характер кривой также без больших просадок).

Файлы:
 

Еще пример пробойной стратегии DonchianBreakout.

Стратегия DonchianBreakout

Настройки тестирования:

Настройки тестирования советника DonchianBreakoutFilteredL1.mq5

1. Входные параметры без фильтров:

Входные параметры тестирования советника DonchianBreakoutFilteredL1.mq5 без фильтров

Результат тестирования советника без фильтров:

Результат тестирования советника DonchianBreakoutFilteredL1.mq5 без фильтров

2. Входные параметры советника DonchianBreakoutFiltered с L1-фильтром выхода из рынка:

Входные параметры тестирования советника DonchianBreakoutFilteredL1.mq5 с L1-фильтром выхода

Результат тестирования советника DonchianBreakoutFilteredL1.mq5 с L1-фильтром выхода

Результат тестирования советника DonchianBreakoutFilteredL1.mq5 с L1-фильтром выхода

Как и для советника по стратегии ATRChannelBreakout, L1-фильтр выходов в стратегии DonchianBreakout по прибыли не смог превзойти стратегию без фильтров. 

Тем не менее, характер кривых для обоих стратегий свидетельствует о большем времени в прибыли, т.е. согласованы с трендом.

Файлы: