Автор |
Сообщение |
Marcello
Зарегистрирован: 30.05.2015
Сообщения: 69
|
Приветствую!
Вот тут нашел красивое решение с фракталами:
Код: |
_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
|
Вроде так. Не проверял.
Код: |
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
|
Спасибо за наводку. Вот, что в итоге получилось с небольшими доработками:
Код: |
// внес в параметры массивы фракталов 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
|
Оказывается, фракталы не всегда чередуются. Значит, в промежутки между однонаправленными фракталами нужно вставить фрактал противоположного направления. С циклами получилось так:
Код: |
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
|
Давай код целиком. Так не могу определить почему цикл бесконечный. |
_________________ ceterum censeo carthaginem esse delendam
Удачи. Олег. |
|
Посмотреть профиль Отправить личное сообщение Посетить сайт автора |
|
Marcello
Зарегистрирован: 30.05.2015
Сообщения: 69
|
Код: |
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
|
У тебя во всех циклах используется i. Похоже, что I глобальтная, а ты ее то так то так переназначаешь. Сделай в разных циклах разный индекс (i, j, k, m...). |
_________________ ceterum censeo carthaginem esse delendam
Удачи. Олег. |
|
Посмотреть профиль Отправить личное сообщение Посетить сайт автора |
|
Marcello
Зарегистрирован: 30.05.2015
Сообщения: 69
|
Ты прав. Проблема была из-за итераторов. Теперь все ок. Спасибо. |
|
|
Посмотреть профиль Отправить личное сообщение |
|
|
|
Следующая тема
Предыдущая тема
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете голосовать в опросах Вы не можете вкладывать файлы Вы не можете скачивать файлы
|
|