Список форумов AmiSite.ru AmiSite.ru
Форум по Ами
 FAQ  •  Поиск  •  Пользователи  •  Группы   •  Регистрация  •  Профиль  •  Войти и проверить личные сообщения  •  Вход
 Вариация на тему фракталов. Как написать такую штуку? Следующая тема
Предыдущая тема
Начать новую тему  Ответить на тему
Автор Сообщение
Marcello



Зарегистрирован: 30.05.2015
Сообщения: 69

СообщениеДобавлено: Пн Авг 22, 2016 10:20 pm Ответить с цитатой Вернуться к началу

Приветствую!
Вот тут нашел красивое решение с фракталами:
Код:
_SECTION_BEGIN( "Fractal" );
FractalPeriod = Param( "Fractal period", 5, 3, 25, 2 );
FractalColor = ParamColor( "Fractal color", colorBlue );
HighFractal = HHV( Ref( High, int( FractalPeriod / 2 ) ), FractalPeriod ) == High;
LowFractal = LLV( Ref( Low, int( FractalPeriod / 2 ) ), FractalPeriod ) == Low;
PlotShapes( IIf( HighFractal, shapeDownTriangle, shapeNone ), FractalColor, 0, High );
PlotShapes( IIf( LowFractal, shapeUpTriangle, shapeNone ), FractalColor, 0, Low );
_SECTION_END();

Подскажите, как посчитать среднее расстояние между фракталами? В идеале хотелось бы получить функцию примерно такого вида:
Код:
function getSize( fsize, fdir, fcount ), где
fsize - размерность фрактала
fdir - направление фрактала: -1 только нижние, 1 только верхние, 0 любые
fcount - количество последних фракталов, для которых нужно посчитать среднее расстояние.
Догадываюсь, что нужно определить самый последний фрактал, который сформировался (но без заглядывания вперед!), потом отсчитать назад нужное количество фракталов и разделить расстояние между этими барами на заданное количество фракталов, но закодить это не получается.
Посмотреть профиль Отправить личное сообщение
000
Site Admin


Зарегистрирован: 10.12.2007
Сообщения: 9106

СообщениеДобавлено: Вт Авг 23, 2016 12:21 am Ответить с цитатой Вернуться к началу

Вроде так. Не проверял.
Код:
function getSize( fsize, frdir, fcount )
{
   HighFractal = HHV( Ref( High, int( fsize / 2 ) ), fsize ) == High;
   LowFractal = LLV( Ref( Low, int( fsize / 2 ) ), fsize ) == Low;
   fract = IIf(frdir == 1, HighFractal, IIf(frdir == -1, LowFractal, HighFractal OR LowFractal));
   fr = Av = 0;
   for(i = BarCount - 1; i > 1; i--)
   {
      if(fr < fcount)
      {
         if(fract[i])
            fr++;
      }   
      else
      {
         Av = (BarCount - 1 - i)/fcount;
         i = 1;
      }
   }
   return Av;
}

_________________
ceterum censeo carthaginem esse delendam
Удачи. Олег.
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
Marcello



Зарегистрирован: 30.05.2015
Сообщения: 69

СообщениеДобавлено: Вт Авг 23, 2016 9:55 am Ответить с цитатой Вернуться к началу

Спасибо за наводку. Вот, что в итоге получилось с небольшими доработками:
Код:
// внес в параметры массивы фракталов HighFractal, LowFractal, чтоб не пересчитывать каждый раз
// добавил x - текущий бар, для которого ищем расстояние
function getSize( x, fsize, frdir, fcount, HighFractal, LowFractal )
{
    fract = IIf( frdir == 1, HighFractal, IIf( frdir == -1, LowFractal, HighFractal OR LowFractal ) );
    fr = Av = firstFrac = 0;
    // считаем фракталы с текущего бара x за вычетом половины размера фрактала
    beginFrom = x - ( fsize - 1 ) / 2;

    for ( i = beginFrom; i > 1; i-- )
    {
        if ( fr < fcount )
        {
            if ( fract[i] )
            {
                fr++;
                // конец отрезка считаем с первого найденного фрактала
                if ( fr == 1 ) firstFrac = i;
            }
        }
        else
        {
            // делим на fcount - 1, т.к. между 2 фракталами отрезок один
            Av = ( firstFrac - i - 1 ) / ( fcount - 1 );
            i = 1;
        }
    }

    return Av;
}

Функция используется так:
Код:
s = 0;
for ( i = FractalPeriod * 2; i < BarCount; i++ )
{
    s[i] = getSize( i, FractalPeriod, -1, 2, HighFractal, LowFractal );
}
Plot( s, "s", 55, styleOwnScale );
Посмотреть профиль Отправить личное сообщение
Marcello



Зарегистрирован: 30.05.2015
Сообщения: 69

СообщениеДобавлено: Вт Авг 23, 2016 11:04 pm Ответить с цитатой Вернуться к началу

Оказывается, фракталы не всегда чередуются. Значит, в промежутки между однонаправленными фракталами нужно вставить фрактал противоположного направления. С циклами получилось так:
Код:
lastDir = x1 = z = 0;
fract = HighFractal OR LowFractal;
for ( i = 0; i < BarCount; i++ ) {
   if ( NOT fract[i] ) continue;

   if ( lastDir == 0 )
   if ( fract[i] == HighFractal[i] ) { lastDir = 1; x1 = i; continue; }

   if ( lastDir == 0 )
   if ( fract[i] == LowFractal[i] ) { lastDir = -1; x1 = i; continue; }
   
   if ( lastDir == 1 ) {
      if ( fract[i] == HighFractal[i] ) { z = getExtreme( x1 + 1, i, -1 ); LowFractal[z] = 1; }
      if ( fract[i] == LowFractal[i] ) lastDir = -1;
      x1 = i; continue;
   }
   
   if ( lastDir == -1 ) {
      if ( fract[i] == LowFractal[i] ) { z = getExtreme( x1 + 1, i, 1 ); HighFractal[z] = 1; }
      if ( fract[i] == HighFractal[i] ) lastDir = 1;
      x1 = i; continue;
   }
}

Функция, которая ищет промежуточный экстремум, выглядит так:
Код:
// x1 - первый бар
// x2 - последний бар
// xdir - направление: 1 - вверх, -1 - вниз
function getExtreme( x1, x2, xdir ) {
   Result = x1;
   Val = iIf( xdir == -1, L[x1], H[x1] );
   for ( i = x1 + 1; i < x2; i++ ) {
      if ( xdir == -1 )
      if ( L[i] <= Val ) { Val = L[i]; Result = i; }
      if ( xdir == 1 )
      if ( H[i] >= Val ) { Val = H[i]; Result = i; }
   }
   return Result;
}

Фракталы рисуются правильно, но появилась ошибка вот тут:
Код:
s = 0;
for ( i = FractalPeriod * 2; i < BarCount; i++ )
{
    s[i] = getSize( i, FractalPeriod, -1, 2, HighFractal, LowFractal );
}

Пишет: Error 15. Endless loop detected in FOR loop
Посмотреть профиль Отправить личное сообщение
000
Site Admin


Зарегистрирован: 10.12.2007
Сообщения: 9106

СообщениеДобавлено: Ср Авг 24, 2016 8:13 am Ответить с цитатой Вернуться к началу

Давай код целиком. Так не могу определить почему цикл бесконечный.

_________________
ceterum censeo carthaginem esse delendam
Удачи. Олег.
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
Marcello



Зарегистрирован: 30.05.2015
Сообщения: 69

СообщениеДобавлено: Ср Авг 24, 2016 9:07 am Ответить с цитатой Вернуться к началу

Код:
FractalPeriod = Param( "Fractal period", 5, 3, 25, 2 );
HighFractal = HHV( Ref( High, int( FractalPeriod / 2 ) ), FractalPeriod ) == High;
LowFractal = LLV( Ref( Low, int( FractalPeriod / 2 ) ), FractalPeriod ) == Low;


// x1 - первый бар
// x2 - последний бар
// xdir - направление: 1 - вверх, -1 - вниз
function getExtreme( x1, x2, xdir )
{
    Result = x1;
    Val = iIf( xdir == -1, L[x1], H[x1] );

    for ( i = x1 + 1; i < x2; i++ )
    {
        if ( xdir == -1 )
            if ( L[i] <= Val )
            {
                Val = L[i];
                Result = i;
            }

        if ( xdir == 1 )
            if ( H[i] >= Val )
            {
                Val = H[i];
                Result = i;
            }
    }

    return Result;
}


lastDir = x1 = z = 0;
fract = HighFractal OR LowFractal;

for ( i = 0; i < BarCount; i++ )
{
    if ( NOT fract[i] )
        continue;

    if ( lastDir == 0 )
        if ( fract[i] == HighFractal[i] )
        {
            lastDir = 1;
            x1 = i;
            continue;
        }

    if ( lastDir == 0 )
        if ( fract[i] == LowFractal[i] )
        {
            lastDir = -1;
            x1 = i;
            continue;
        }

    if ( lastDir == 1 )
    {
        if ( fract[i] == HighFractal[i] )
        {
            z = getExtreme( x1 + 1, i, -1 );
            LowFractal[z] = 1;
        }

        if ( fract[i] == LowFractal[i] )
            lastDir = -1;

        x1 = i;

        continue;
    }

    if ( lastDir == -1 )
    {
        if ( fract[i] == LowFractal[i] )
        {
            z = getExtreme( x1 + 1, i, 1 );
            HighFractal[z] = 1;
        }

        if ( fract[i] == HighFractal[i] )
            lastDir = 1;

        x1 = i;

        continue;
    }
}


function getSize( x, fsize, frdir, fcount, HighFractal, LowFractal )

{
    fract = IIf( frdir == 1, HighFractal, IIf( frdir == -1, LowFractal, HighFractal OR LowFractal ) );
    fr = Av = firstFrac = 0;

    beginFrom = x - ( fsize - 1 ) / 2;

    for ( i = beginFrom; i > 1; i-- )
    {
        if ( fr < fcount )
        {
            if ( fract[i] )
            {
                fr++;
                if ( fr == 1 ) firstFrac = i;
            }
        }
        else
        {
            Av = ( firstFrac - i - 1 ) / ( fcount - 1 );
            i = 1;
        }
    }

    return Av;
}


s = 0;

for ( i = FractalPeriod * 2; i < BarCount; i++ )
{
    s[i] = getSize( i, FractalPeriod, -1, 2, HighFractal, LowFractal );
}

Plot( s, "s", 55, styleOwnScale );

Plot( C, "Price", colorDefault, styleBar );
PlotShapes( IIf( HighFractal, shapeDownArrow, shapeNone ), 42, 0, High );
PlotShapes( IIf( LowFractal, shapeUpArrow, shapeNone ), 43, 0, Low );


Теперь в том же месте пишет: Error 10. Subscript out of range. You must not access array elements outside 0..(BarCount-1) range
Посмотреть профиль Отправить личное сообщение
000
Site Admin


Зарегистрирован: 10.12.2007
Сообщения: 9106

СообщениеДобавлено: Ср Авг 24, 2016 11:02 am Ответить с цитатой Вернуться к началу

У тебя во всех циклах используется i. Похоже, что I глобальтная, а ты ее то так то так переназначаешь. Сделай в разных циклах разный индекс (i, j, k, m...).

_________________
ceterum censeo carthaginem esse delendam
Удачи. Олег.
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
Marcello



Зарегистрирован: 30.05.2015
Сообщения: 69

СообщениеДобавлено: Ср Авг 24, 2016 11:16 am Ответить с цитатой Вернуться к началу

Ты прав. Проблема была из-за итераторов. Теперь все ок. Спасибо.
Посмотреть профиль Отправить личное сообщение
Показать сообщения:      
Начать новую тему  Ответить на тему


 Перейти:   



Следующая тема
Предыдущая тема
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете вкладывать файлы
Вы не можете скачивать файлы


Powered by phpBB © 2001, 2002 phpBB Group :: FI Theme :: Часовой пояс: GMT + 3

File Attachment © by Meik Sievertsen