советник - разные вопросы - страница 4

 
  1. Да, они активно используют его. Все это было написано, когда были только валюты. Теперь есть металлы, и если размер тика != пункт, то это категорически неверно.
  2. 02:00:00.069 - пользовательский эксперт EURUSD, H1: | _lotSize - NormalizeDouble: 0.07000000000000001
    ОП продолжает печатать двойку до 15 цифр и не может понять, почему это не 0.07 точно. Потому что какое-то число нельзя представить точно 1/8. можно 1/10. нельзя.
 
honest_knave:
double LotCalculator(double lots)
  {
   ...
   return(NormalizeDouble(lots,2));
  }

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

Я все еще беспокоюсь о'NormalizeDouble' и ищу другой способ, какой из них лучше, чем 'NormalizeDouble'.

Спасибо!

 

Большое спасибо тем, кто писал комментарии.

@whroeder1- Я буду широко изучать ваш комментарий (/ ссылки) большое спасибо.
@Marco- Я буду использовать его после выпуска LotSize LotStep. Спасибо!

 
Max Enrik:

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

Я все еще беспокоюсь о'NormalizeDouble' и ищу другой способ, какой из них лучше, чем 'NormalizeDouble'.

Спасибо!

Возможно, было бы лучше установить, чего именно вы хотите достичь.

Если вы хотите, чтобы функция возвращала действительный размер лота для размещения ордера, вам не нужно использовать NormalizeDouble(). Мой оригинальный фрагмент кода или WHRoeder's достигнут этого для вас. Между ними есть тонкие различия, которые являются вопросом личных предпочтений.

Но если вы сделаете прямой Print() этого значения лота, вы можете получить некоторые "странные" результаты... например, 0.07000000000000001.

Это не будет проблемой для OrderSend(), но это может быть не то, что вы ожидаете увидеть.

Если вы хотите, чтобы числа отображались в "нормальном" виде, у вас есть 2 варианта:

1. Вы можете использовать NormalizeDouble() в функции. При стандартной распечатке значение будет таким, каким вы его ожидаете увидеть. Но если вы (вручную) напечатаете достаточное количество десятичных знаков, то в конце концов увидите, что число не совсем такое, как вы думаете. Именно эту мысль пытается донести WHRoeder (как мне кажется). Это решение не самое элегантное, но самое простое. Или...

2. Вы можете оставить размер лота как есть (т.е. не использовать NormalizeDouble) и затем корректировать значение для отображения, когда это необходимо. Для этого можно использовать DoubleToStr() или StringFormat() или printf(), в зависимости от того, что вам нужно. Это более гибкий подход.

Помните, что фактическое значение и способ его отображения не обязательно должны совпадать. Вы никогда не сможете хранить ровно 0,07:

   double myVal=0.07;
   printf("%.24f",myVal);

Result: 0.070000000000000006661338

Но вы можете отобразить 0,07, если вам это необходимо.
 
honest_knave:

Возможно, было бы лучше установить, чего именно вы хотите добиться.
...

Вау, хорошо, что вы написали это, я почти понял, как ваш комментарий.
Так что я напишу новый комментарий, скоро.

//--- второй раз редактировалось

Как я уже говорил, мне не нужно, чтобы LotSize и LotStep отображались правильно только на дисплее, мне нужно, чтобы LotSize и LotStep отображались везде одинаково.
Просто я беспокоюсь об этом.

 

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

//Gearbox//
double Lots;
Balance=AccountInfoDouble(ACCOUNT_BALANCE);

if(Balance>10000)
{Lots=10;Print(" Gear Two");}
if(Balance>100000)
{Lots=100;Print(" Gear Three");}
if(Balance>1000000)
{Lots=1000;Print(" Gear Four");}
if(Balance>10000000)
{Lots=10000;Print(" Gear Five");}

if(Balance<10000000)
{Lots=1000;Print(" Gear Four");}
if(Balance<1000000)
{Lots=100;Print(" Gear Three");}
if(Balance<100000)
{Lots=10;Print(" Gear Two");}
if(Balance<10000)
{Lots=1;Print(" Gear One");}
if(Balance>1000000000)
{Lots=0;}
 

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

Пожалуйста, дайте мне хороший (понятный) совет или помощь, заранее спасибо.

void OnChartEvent(const int      id     , // Event ID
                  const long   & lparam , // Parameter of type long event
                  const double & dparam , // Parameter of type double event
                  const string & sparam   // Parameter of type string events
                  )
{

    _lotCalc();
    //-------Process Button---------------------------------------------------------|
    if ( sparam == _btnLotMinus )
    {
        ObjectSetInteger( 0, _btnLotMinus, OBJPROP_STATE, false );
        _lotSize -= _lotStep;

        if ( NormalizeDouble( _lotSize, 2 ) <= 0 ) _lotSize = _lotMin;
        _calcUpdade( CALC_CHANGE_LOT );

        Print( " | Lot:   ", _lotSize );
        return;
    }   //---if Close
    //                          ...
}

double _lotCalc()
{
    //---
    _lotMin  = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MIN  );
    _lotMax  = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MAX  );
    _lotStep = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_STEP );

    //---
    return( NormalizeDouble( _lotSize, 2 ) );
}
 
Max Enrik:

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

Пожалуйста, дайте мне хороший (понятный) совет или помощь, заранее спасибо.

Поздно ночью, некомпилированный, непроверенный.

Мы не видим, где вы впервые установили _lotSize... помните, что вам нужно убедиться, что _lotSize всегда кратен _lotStep.

ИМХО было бы лучше, если бы вы держали все расчеты лота вместе, а не разделяли их между OnChartEvent() и _lotCalc(). Одна функция, которая проверяет min / max / шаг и выполняет инкремент / декремент.

void OnChartEvent(const int      id     , // Event ID
                  const long   & lparam , // Parameter of type long event
                  const double & dparam , // Parameter of type double event
                  const string & sparam   // Parameter of type string events
                  )
{
    _lotCalc();
    //-------Process Button---------------------------------------------------------|
    if ( sparam == _btnLotMinus )
    {
        ObjectSetInteger( 0, sparam, OBJPROP_STATE, false );
        _lotSize = fmax(_lotMin, _lotSize-_lotStep);
        _calcUpdade( CALC_CHANGE_LOT );
        printf( " | Lot: %.2f  ", _lotSize );
        return;
    }   //---if Close
    //                          ...
}

void _lotCalc()
{
    //---
    _lotMin  = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MIN  );
    _lotMax  = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MAX  );
    _lotStep = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_STEP );

    //---
}
 
honest_knave:

Поздно ночью, не скомпилировано, не протестировано.
Мы не видим, где вы впервые установили _lotSize... помните, что вам нужно убедиться, что _lotSize всегда кратен _lotStep.
ИМХО было бы лучше, если бы вы держали все расчеты лота вместе, а не разделяли их между OnChartEvent() и _lotCalc(). Одна функция, которая проверяет min / max / шаг и выполняет инкремент / декремент.

Это очень помогло мне, то есть решило мои проблемы с lotSize и losStep.
Огромная благодарность.

#Lot 0 (ноль) & (между решением проблемы размера лота и шага лота) - закрыто

 

Да, я забыл код lotSize, поэтому я использую его в функцииinit.
Является ли это хорошим местом для _lotSize?

Спасибо!

int OnInit()
{
    _pip = Point;
    if( Digits == 0 || Digits == 2 || Digits == 3 || Digits == 5 ) _pip = 10 * Point;
    _lotSize = _lotValue * MarketInfo( Symbol(), MODE_MINLOT );

    //...
}