Qualsiasi domanda da principiante, per non ingombrare il forum. Professionisti, non passate oltre. Da nessuna parte senza di te - 6. - pagina 641

 
simpleton:

Perché emulare un errore?

Errore - serve a segnalare che, per qualche motivo legato a limitazioni/fallimenti del sistema, l'algoritmo non ha potuto essere eseguito e il risultato ottenuto con alcune garanzie (limitate, ovviamente, ma - ). La funzione FillAndPrint() mostra eloquentemente cosa significa una situazione di errore e cosa no. Quando si verifica un errore, non prova nemmeno a stampare il risultato. Se non ci sono errori, il risultato può essere affidabile. Questo è il modo in cui la logica di errore/non errore dovrebbe essere costruita.

Qui devi modificare l'algoritmo: devi applicare un filtro aggiuntivo.

Questo è il modo in cui dovrebbe essere fatto:

In primo luogo, "filtriamo" per tipi di oggetti e parametri, selezionando solo gli oggetti di cui abbiamo bisogno tra tutti quelli disponibili, e poi applichiamo un ulteriore filtro. È più o meno come lo farebbe una persona. È quello che farebbe un umano, giusto?

Per ognuno di questi piccoli sottocompiti, è auspicabile una funzione separata.

Non ci dovrebbero essere numeri nelle espressioni, tranne in casi molto speciali, per esempio se è necessario raddoppiare ed è nella natura dell'algoritmo farlo. Allora il numero 2 può essere usato direttamente nelle espressioni. E in altri casi così rari.

In altri casi, si dovrebbe usare la mnemotecnica. In primo luogo, migliorano notevolmente la comprensione di ciò che sta accadendo in un dato luogo, e quindi aiutano a ridurre la probabilità di commettere un errore. E in secondo luogo, il valore stesso è definito in un posto ed è facile cambiarlo se necessario, e sarà impossibile fare un errore rispetto al caso in cui il numero è usato nell'algoritmo più di una volta, e senza usare la mnemotecnica si devono fissare i numeri in diversi punti dell'algoritmo.

Risultato della corsa:

Non si trova un solo oggetto. Aumentate i valori di entrambe le mnemoniche 10 volte fino a 36000 (10 ore), ed eseguite di nuovo:

Una tendenza ha già "superato" il filtraggio. Ora ripristiniamo il valore del primo mnemonico a 3600 ed eseguiamo:

Si può vedere che entrambe le tendenze hanno ormai "superato" il filtraggio. A proposito, consiglio di fare il debug di tutti i rami (parti) del programma in questo modo, piuttosto che di un solo ramo.

Per aiutare a formalizzare in qualche modo, cercherò di spiegarlo in questo modo. Il programma è apparentemente come un piano.

Ogni elemento principale del piano può essere suddiviso in elementi più piccoli del sottopiano. Quelli più piccoli in altri ancora più piccoli. Gli elementi dei sottopiani più piccoli vengono eseguiti direttamente.

Ogni piano, sottopiano e anche i più piccoli sottopiani corrispondono a funzioni nel programma. Gli elementi nei sottopiani più piccoli corrispondono a funzioni "finali" che chiamano solo funzioni di sistema o addirittura non le chiamano, per esempio, AddValue() o DiffInSecs() sono esempi di quelle discusse sopra. Gli elementi del sottopiano sopra corrispondono alle funzioni che chiamano le funzioni che implementano gli elementi del sottopiano sotto. In quelli discussi sopra, questi sono MassTrendNumber(), AddValueIfFound(), AddValueIfFiltered(). Le funzioni di "basso livello" non dovrebbero chiamare funzioni di "alto livello", e le funzioni di "alto livello" fondamentalmente non dovrebbero saltare diversi livelli verso il basso, cioè dovrebbero chiamare solo funzioni fondamentalmente al livello inferiore. Questa regola è molto più severa per "basso livello" che per "alto livello".

Provate a costruire i vostri programmi organizzando le azioni in essi come funzioni (brevi) collegate da questo tipo di struttura ad albero, nel senso di chi chiama chi.

Questo programma ha un albero degenerato: un ramo che si "ramifica" più volte. E si "ramifica" non in due piccoli rami, ma in uno solo. Ma il punto che le funzioni di "alto livello" chiamano costantemente quelle di "basso livello" può essere visto. In questa modifica, ho inserito un ulteriore livello in questa struttura, un ulteriore "ramo non ramificato" - AddValueIfFiltered().

Sto incollando il codice pronto.

Il compito: cercare le linee di tendenza(OBJ_TREND) e registrare i valori dei prezzi relativi alla barra corrente in un array. Filtrato contro l'esistenza di parametri di tempo dell'oggetto (OBJ_TREND).

#property strict

/******************************************************************************/
bool AddValue(double &array[], const double value) {
  const int size = ArraySize(array);

  if (ArrayResize(array, size + 1) != size + 1) {
    return false; // Ошибка, значение не может быть добавлено к массиву
  }

  array[size] = value; //записываем
  return true; // Нет ошибки, значение добавлено к массиву
}

/******************************************************************************/
bool AddValueIfFound(double &array[], const string name) {
  const int type = ObjectType(name);

  if (type == OBJ_TREND) {
    switch ((color)ObjectGet(name, OBJPROP_COLOR)) { // Тип color допустимо использовать в switch
    case Goldenrod:
    case Gainsboro:
    case White:
      if (!AddValueIfFiltered(array, name)) { // Пропускаем через фильтр
        return false;
      }
    }
  }

  return true; // Нет ошибки, значение, если найдено, добавлено к массиву
}
/******************************************************************************/
bool MassTrendNumber(double &array[], const bool buy) { // Поиск значения цены трендовой линии, текущего бара, запись в массив. Два массива: masS и masB
  const string subname = (buy ? "uptrendline" : "downtrendline"); // существует два названия трендовых линий, первое и второе

  if (ArrayResize(array, 0) != 0) {
    return false; // Ошибка, массив не может быть заполнен достоверно
  }

  for (int i = 0, limit = ObjectsTotal(OBJ_TREND); i < limit+2; i++) {
    if (!AddValueIfFound(array, subname + IntegerToString(i))) {
      return false; // Ошибка, массив, если и заполнен, то недостоверно
    }
  }
 
  return true; // Нет ошибки, массив заполнен достоверно
}
/******************************************************************************/
long DiffInSecs(const datetime dt1, const datetime dt2) {
  return dt1 - dt2;
}
/******************************************************************************/
bool AddValueIfFiltered(double &array[], const string name) {
#define MIN_SECS_BETWEEN_PRICE1_AND_PRICE2 3600
#define MAX_SECS_AFTER_PRICE2              3600

  const datetime dt1 = (datetime)ObjectGet(name, OBJPROP_TIME1);
  const datetime dt2 = (datetime)ObjectGet(name, OBJPROP_TIME2);
  const datetime dt = TimeCurrent();
  
  Print("name = ", name,// ", dt = ", dt, ", dt1 = ", dt1,"\n", 
  " DiffInSecs = ", DiffInSecs(dt,dt2)," DiffInSecs = ", DiffInSecs(dt2,dt1));

   if( DiffInSecs(dt,dt2)>MAX_SECS_AFTER_PRICE2 && DiffInSecs(dt2,dt1)> MIN_SECS_BETWEEN_PRICE1_AND_PRICE2){
    if (!AddValue(array, ObjectGetValueByShift(name, 1))) { // Пытаемся добавить
      return false; // Ошибка, значение не добавлено
    }
  }

  return true; // Нет ошибки, значение, если удовлетворило условию фильтра, добавлено к массиву
}

/******************************************************************************/
void FillAndPrint(double &array[], const bool buy) {
  if (MassTrendNumber(array, buy)) {
    const int limit = ArraySize(array);

    Print("Найдено объектов: ", limit);

    for (int i = 0; i < limit; i++) {
      Print("Price[", i, "] = ", DoubleToStr(array[i], Digits));
    }
  } else {
    Print("Чёрт!");
  }
}

/******************************************************************************/
void OnTick()

//=============================================================================================
//====================================== Линии тренда =========================================
//=============================================================================================
 double masS[]; double masB[];

  Print("Sell:");
  FillAndPrint(masS, false);

  Print("Buy:");
  FillAndPrint(masB, true);
 simpletonСпасибо вам большое, вы за пестовали меня на ощущения правильного кода!) (Правда я немногое понял))))
 
evillive:

Ho 4 cifre ora, su ewardollar a 1 lotto 1 punto costa 10 dollari ed è sempre stato così. Per le croci il costo sarà da 8 a 16, la formula è un po' più complicata.

Per esempio, per l'euro sterlina marketinfo ha restituito 16,984, il tasso di cambio sterlina-dollaro = 1,6984, cioè 1 pip dell'euro sterlina vale 1 sterlina, moltiplicato per il valore del punto sterlina-dollaro, che è sempre 10,0 (100000 * 0,0001 = 10,0 o 100000 * 0,00010 = 10,0 - come si vuole).


Tutti questi calcoli sono corretti solo se il vostro conto è in dollari:

In questo caso, per xUSD (EURUSD, GBPUSD ecc.) tickvalue = lot*point = 100000*0.0001 = 10.0

per USDh (USDCHF, USDJPY ecc.) tickvalue = lot*point/Bid = 100000*0.01/101.93=9.8107

per xUSD/yUSD (EURGBP) tickvalue = Bid(yUSD)*lot*point = 1.6980*100000*0.0001 = 16.98

per xUSD/USDy (EURJPY) tickvalue = lot*point/Bid(USDy) = 100000*0.01/101.91 = 9.8126


Qualcosa che hai incasinato! Si è preso il tempo di guardare il codice, le espressioni selezionate e guardare:

  double TV = MarketInfo(Symbol(),MODE_TICKVALUE); 
  string sTV = DoubleToStr(TV,4); 
  Comment("TV ",sTV); //sTV = 1.0/Bid

Non potrebbe essere più semplice! No 10, 16, ecc.

 
evillive:

Ho 4 cifre ora, su ewardollar a 1 lotto 1 punto costa 10 dollari ed è sempre stato così. Per le croci il costo sarà da 8 a 16, la formula è un po' più complicata.

Per esempio, per la sterlina euro marketinfo ha restituito 16,984, il tasso di cambio sterlina-dollaro = 1,6984, cioè 1 punto della sterlina euro vale 1 sterlina, moltiplicato per il valore del punto sterlina-dollaro, che è sempre 10,0 (100000 * 0,0001 = 10,0 o 100000 * 0,00010 = 10,0 - come si vuole).


Tutti questi calcoli sono corretti solo se il vostro conto è in dollari:

In questo caso, per xUSD (EURUSD, GBPUSD ecc.) tickvalue = lot*point = 100000*0.0001 = 10.0

per USDx (USDCHF, USDJPY ecc.) tickvalue = lot*point/Bid = 100000*0.01/101.93 = 9.8107

per xUSD/yUSD (EURGBP) tickvalue = Bid(yUSD)*lot*point = 1.6980*100000*0.0001 = 16.98

per i cross xUSD/USDy (EURJPY) tickvalue = lot*point/Bid(USDy) = 100000*0.01/101.91=9.8126




Questo è sbagliato! Il valore di una citazione non ha importanza!E il valore di un tick minimo deve essere calcolato a partire dal prezzo corrente! Che è uguale a TICK_VALUE! Qui sopra c'è un esempio del mio codice.
 
borilunad:

borilunad:

Questo è sbagliato! Il valore di una citazione è irrilevante! E il valore di un min.tick dovrebbe essere calcolato dal prezzo corrente! Che è uguale a TICK_VALUE! Qui sopra c'è un esempio del mio codice.

In che modo è sbagliato? Marketinfo restituisce gli stessi valori delle formule che ho dato sopra. Non ho inventato io queste formule, sono usate dal terminale per calcolare TickValue).

È chiaro che è più conveniente prendere il valore da Marketinfo, ma lui chiedeva formule o metodi di calcolo.

E riguardo al valore che ho scritto prima, che non importa, perché nei conteggi a 5 cifre un punto = 10 pips, ed è lo stesso punto da 4 cifre.

 
evillive:

In che modo è sbagliato? Marketinfo restituisce gli stessi valori delle formule che ho dato sopra. Non ho inventato queste formule, sono usate dal terminale per calcolare TickValue))

È chiaro che è più conveniente prendere il valore da Marketinfo, ma lui chiedeva formule o metodi di calcolo.

E ho scritto prima sulla signitude, che non importa, perché sui conteggi a 5 cifre un punto = 10 pips, e questo è lo stesso punto da 4 cifre.


Questo è ciò che intendo perMarketInfo(Symbol(),MODE_TICKVALUE) =1.0/Bid;Forse solo per l'Eurodollaro, non lo spruzzo sugli altri!
 
borilunad:

Questo è ciò che intendo conMarketInfo(Symbol(),MODE_TICKVALUE) =1.0/Bid;Forse, solo per Euro, non per altri!

Questo è esattamente ciò che è sbagliato con l'eurodollaro, in base alla definizione data nella guida

MODE_TICKVALUE

16

Cambiamento minimo del prezzo del titolo nella valuta del deposito


E significa moltiplicare

MODO_POINT

11

Dimensione del punto nella valuta della citazione. Per il simbolo corrente è memorizzato nella variabile predefinita Point


da

MODE_LOTSIZE

15

Dimensione del contratto nella valuta di base dello strumento


Naturalmente, se il tuo conto è in Euro, dovresti usare l'Euro come valuta di base, ma per i trader che hanno un conto in dollari (lo fanno più spesso), le formule di cui sopra sono valide. Poiché le coppie principali e più scambiate sono basate sul dollaro USA, queste formule sono usate più spesso.

 
evillive:

Questo è esattamente sbagliato, in base alla definizione data nell'aiuto

MODE_TICKVALUE

16

Cambiamento minimo del prezzo del simbolo nella valuta del deposito


Significa che dovresti moltiplicare

MODO_POINT

11

Dimensione del punto nella valuta della citazione. Per il simbolo corrente è memorizzato nella variabile predefinita Point


su

MODE_LOTSIZE

15

Dimensione del contratto nella valuta di base dello strumento


Naturalmente, se il tuo conto è in euro, dovresti usare gli euro, ma la maggior parte dei trader ha un conto in dollari.


Bene, allora, ho un caso particolare, ma per me che vivo nella zona euro, è più comodo fare tutti i calcoli in euro!
 

Signori, vi prego di darmi un esempio di codice per il seguente indicatore. Non riesco a capire quanti buffer sono necessari, che tipo di mappatura e dove e quali proprietà dovrebbero essere prescritte per loro.

L'indicatore è il seguente:

1 Le barre si collegano almeno ogni terza barra e quelle adiacenti. La linea è rossa.

2 sezioni di barre collegano i massimi di ogni quinta barra e di quelle adiacenti. La linea è blu.

La cosa principale: i segmenti non si intersecano in alcun modo. L'inizio e la fine di ogni segmento sono indipendenti dagli altri segmenti.

L'indicatore calcola i valori dell'inizio e della fine di ogni segmento. Dovrebbero essere colorati in modo diverso a seconda delle condizioni.

Questo è più o meno come dovrebbe essere


 

E un'altra domanda.

È normale che non possa lavorare con l'indicatore in modalità Debug.

Quando il programma raggiunge il punto di arresto, il terminale MT4 si blocca e la finestra diventa bianca (in HP) così che è impossibile vedere ciò che è disegnato sul grafico

 
Top2n:

Ecco il codice pronto.

Compito: cerca le linee di tendenza (OBJ_TREND), registra i valori dei prezzi relativi alla barra corrente in un array. Con filtraggio rispetto all'esistenza di parametri temporali dell'oggetto (OBJ_TREND).

simpleton:Grazie mille, mihai fatto sentire il codice giusto!) (Anche se non ho capito molto))))

Se si pratica, la comprensione arriverà, sempre di più. Ci vuole concentrazione e attenzione. Quando l'algoritmo del programma è spalmato su una grande funzione, è difficile realizzarlo con concentrazione e attenzione - si formano troppi collegamenti. Ma se un programma è diviso in parti funzionalmente complete (piccole funzioni), è molto più facile farlo per ogni piccola funzione separata. E così ad ogni livello di funzione. A proposito:

   if( DiffInSecs(dt,dt2)>MAX_SECS_AFTER_PRICE2 && DiffInSecs(dt2,dt1)> MIN_SECS_BETWEEN_PRICE1_AND_PRICE2){
    if (!AddValue(array, ObjectGetValueByShift(name, 1))) { // Пытаемся добавить
      return false; // Ошибка, значение не добавлено
    }
  }
Devo aver sbagliato il nome del mnemonico MAX_SECS_AFTER_PRICE2 (perché all'inizio avevo capito che la condizione doveva essere inversa), il significato dovrebbe probabilmente essere MIN_SECS_AFTER_PRICE2, cioè il minimo consentito, non il massimo.