М
Қар. 16, 2017, 1:42 Т.Қ.

Падает скорость вычисления массивов

Qt, QVector

Здравствуйте. Произвожу вычисления с участием массивов. Первые вычисления производит быстро. Далее скорость падает в геометрической прогрессии. Ниже код. Скажите пожалуйста, в чем причина и как ее исправить?
#include "mainwindow.h"
#include "ui_mainwindow.h"

void MainWindow::StrategyCod() //код стратегии
{
  for (int NMA=5;NMA<1000;NMA=NMA+50)//3-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  {
      //----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
      int NOpenPosition=0; //число открытых позиций
      double Profit=0;
      double PriceEnter,PriceExit; //цена входа и выхода
      QDate DateOpenPosition; //Дата открытия позиции
      //----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    //int NMA=20;//период ma
    QVector<double> SMA(NBar); //ma
    for(long long bar = NMA; bar <NBar; bar++) //ma
    {
        double Summa=0;//summa
        for(long long i=bar-NMA;i<bar;i++)//summa
        {
            Summa=Summa+Close[i];
        }
        SMA[bar]=Summa/NMA;
    }


    for(long long bar = NMA; bar <NBar; bar++)//основной цикл
    {
     if (NOpenPosition!=0)//2-------------------------------------------------------------------------------------------------------------------------------------------------------
         {
             if ((Close[bar-1]<SMA[bar-1])&&(Close[bar]>SMA[bar]))
             {
                 PriceExit=Close[bar]-qrand()%MaxSlippage; //цена закрытия позиции
                 if (PriceEnter>High[bar]){PriceEnter=High[bar];}
                 if (PriceEnter<Low[bar]){PriceEnter=Low[bar];}
                 NOpenPosition=NOpenPosition-1;
                 Profit=PriceEnter-PriceExit-Commission;
             }
         }
     else//1--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
         {
             if ((Close[bar-1]>SMA[bar-1])&&(Close[bar]<SMA[bar]))
             {
                 PriceEnter=Close[bar]+qrand()%MaxSlippage; //цена открытия позиции  //покупка
                 if (PriceEnter>High[bar]){PriceEnter=High[bar];}
                 if (PriceEnter<Low[bar]){PriceEnter=Low[bar];}
                 NOpenPosition=NOpenPosition+1;
                 DateOpenPosition=Date[bar];
             }
         }
     //1---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    }//2------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
qDebug()<<NMA;
qDebug()<<Profit;
qDebug()<<QDateTime::currentDateTime();
  }//3------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
}

 

3

Ол саған ұнайды ма? Әлеуметтік желілерде бөлісіңіз!

12
BlinCT
  • Қар. 16, 2017, 2:27 Т.Қ.

У вас очень большие проблемы с синтаксисом.
1. Между знаками < > = - и так далее должны быть пробелы. Не склеивайте все в одно, читать очень-очень тяжело.
2. Во вторых в цикле for используйте всегда префикс ++i вместо постфикса i++ если только вы точно не знаете что вам нужен постфикс.
3. Если у вас не очень сложный и большой цикл for то никогда для индекса не используйте ничего кроме одной буквы.
Неправильно:

for(int NMA=5;NMA<1000;NMA=NMA+50)
Правильно:
for (int i = 5; i < 1000; i = i + 50)
4. нету смысла в цикле обьявлять переменные. В первом цикле у вас

int NOpenPosition=0; //число открытых позиций
double Profit=0;
double PriceEnter,PriceExit; //цена входа и выхода
QDate DateOpenPosition; //Дата открытия позиции

Вынесите все это перед внешним циклом.

5. Во втором цикле нету смысла использовать long long так как исходя из первого цикла у вас од 0 до 1000. А это значит там или обычный int или без знаковый quint32.

Исправте это все и проверте.
И еще, отступы для новой строки должны быть 1 таб это 3 пробела. У вас там походу 2 пробела. Смотрится ужасно.

    Evgenii Legotckoi
    • Қар. 16, 2017, 2:34 Т.Қ.
    • (өңделген)

    День добрый!

    SMA - Средняя скользящая за период значит...
    Причина падения скорости очевидно в том, что циклы внутри циклов напиханы с возрастающим размером QVector. Это всегда ведёт к квадратичной зависимости сложности алгоритма и времени вычисления.
    Вообще, средняя скользящая не должна вычисляться слишком долго. Линейная зависимость от количества элементов в массиве, поскольку её обычно вычисляют всегда за период.
    Скорее всего ваш основной цикл лишний. Вычисления SMA у вас в первом цикле, что происходит в основном мне не ясно.
    Зачем вы поместили сюда открытые позиции? Средняя скользящая это индикатор. А позиции в моём понимании - это сделки, они здесь не нужны при вычислении средней скользящей.
      М
      • Қар. 16, 2017, 2:44 Т.Қ.

      long long нужен, т.к. NBar может быть больше int.

      Использовал for(int NMA=5;NMA<1000;NMA=NMA+50), т.к. предусматривается несколько циклов. И название переменной подразумевает под собой некий смысл.
      Средняя скользящая - необходимый элемент расчета.
      После расчета скользящей прогоняется расчет по открытию и закрытию позиций. Затем пересчитвается скользящая и идет новый расчет.
      Вынес за пределы цикла:
      int NOpenPosition=0; //число открытых позиций
      double Profit=0;
      double PriceEnter,PriceExit; //цена входа и выхода
      QDate DateOpenPosition; //Дата открытия позиции
      Трудность осталась.
      QVector с каждым циклом переопределяется. Разве он от этого увеличиться?
        Evgenii Legotckoi
        • Қар. 16, 2017, 2:49 Т.Қ.
        • (өңделген)

        Напомните смысл SMA и NMA. Насколько помню - это два различных индикатора средней скользящей?
        Не вижу смысла делать расчёт для SMA при каждом расчёте одной позиции NMA. Почему бы не рассчитать отдельно SMA и NMA, а потом уже в цикле сравнить их?

          М
          • Қар. 16, 2017, 2:54 Т.Қ.

          в моем случае, NMA - размер цикла SMA. Размер цикла меняется->нужно менять среднюю.

            Evgenii Legotckoi
            • Қар. 16, 2017, 3:09 Т.Қ.

            Хорошо. Тогда здесь нет ничего удивительного, что увеличивается время подсчёта. Вы увеличиваете NMA, что означает, что для SMA нужно подсчитать больше элементов для расчёта одной точки на графике. Чем больше NMA, тем длительнее расчёт.

            Не думаю, что вы здесь сможете что-то оптимизировать. Можете лишь распараллелить расчёт SMA для различных значений NMA.
              М
              • Қар. 16, 2017, 3:12 Т.Қ.

              Спасибо.

                Evgenii Legotckoi
                • Қар. 16, 2017, 3:16 Т.Қ.

                По поводу распараллеливания. Думаю, что это можно сделать следующим способом.

                Делаете класс, отвечающий за расчёт. Создаёте объект для рассчета этого класса, копируете в него массив для рассчёта вместе со значением NMA, кидаете объект через moveToThread . Он там считает, как посчитал, выдёргиваете из него результат. Таким образом можно будет распараллелить вычисления. Это несколько ускорит подсчёт данных.
                  М
                  • Қар. 16, 2017, 3:53 Т.Қ.

                  Изменил логику расчета, теперь считает все в 1000 раз быстрее.

                    Evgenii Legotckoi
                    • Қар. 16, 2017, 4:13 Т.Қ.

                    Молодцом. В чём заключалось изменение?

                      М
                      • Қар. 16, 2017, 4:46 Т.Қ.

                      Пересчет суммы. Я от предыдущей отнимаю одно и добавляю одно значение, а не пересчитываю все заново.

                        Evgenii Legotckoi
                        • Қар. 16, 2017, 5:24 Т.Қ.
                        • (өңделген)

                        То есть отнимаете первое в сумме значение из предыдущего подсчёта, а добавляете последнее в новом подсчёте. Весьма хорошо. Я как-то об этом не подумал.

                          Пікірлер

                          Тек рұқсаты бар пайдаланушылар ғана пікір қалдыра алады.
                          Кіріңіз немесе Тіркеліңіз