//+------------------------------------------------------------------+ //| Indicator_Painting.mq4 | //| Copyright © 2009, TheXpert | //| theforexpert@gmail.com | //+------------------------------------------------------------------+ #property copyright "Copyright © 2009, TheXpert" #property link "theforexpert@gmail.com" // ==================================================== // Необходимо положить в папку /Experts/Libraries вашего терминала // ==================================================== #property library // ==================================================== // Mark for tops and bottoms // ==================================================== void MarkExtremums( double values[], // Indicator values double& extremums[], // Buffer for extremums int startIndex, // Start index for check (it included) int endIndex, // End index for check (it included) int direction, // DIR_TOP for tops, DIR_BOTTOM for bottoms, DIR_ALL for tops an bottoms double emptyValueUsed) // The value used for "empty" mark { // finding out the loop direction and step int di = -1; if (endIndex > startIndex) di = 1; // brushing for (int i = startIndex; (i >= startIndex && i <= endIndex) || (i >= endIndex && i <= startIndex); i += di) { // to check the extremum we need at least 2 older bars // if they are not available, there is no reason to continue if (i + 2 >= Bars) { continue; } // checking empty values if ( values[i] == emptyValueUsed || values[i + 1] == emptyValueUsed || values[i + 2] == emptyValueUsed || values[i] == EMPTY_VALUE || values[i + 1] == EMPTY_VALUE || values[i + 2] == EMPTY_VALUE ) { continue; } // cleaning current value of marking buffer if (di < 0) extremums[i + 1] = EMPTY_VALUE; // extremum condition -- simple case if ((values[i] - values[i + 1])*(values[i + 1] - values[i + 2]) < 0 && (values[i] - values[i + 1])*direction >= 0) { // if the extremum is available extremums[i + 1] = values[i + 1]; continue; } // extremum condition -- complicated case if (values[i + 1] == values[i + 2] && values[i] != values[i + 1] && (values[i] - values[i + 1])*direction >= 0) { // we have potential extremum -- let's check it // we find the 2nd end for this int index = i + 2; bool found = false; while (index < Bars && values[index] != emptyValueUsed && values[index] != EMPTY_VALUE) { if (values[i + 2] != values[index]) { // got it found = true; break; } index++; } if (!found) { // we have an empty value or history end // both cases mean we haven't extremum continue; } // test complicated extremum if ((values[i] - values[i + 1])*(values[i + 1] - values[index]) < 0) { // got extremum extremums[i + 1] = values[i + 1]; } // else -- got bending } } } // ==================================================== // Mark for crosses // ==================================================== void MarkCrosses( double values1[], // Values of the first indicator double values2[], // Values of the second indicator double& crosses[], // Buffer for their crosses int startIndex, // Start index for check (it included) int endIndex, // End index for check (it included) int direction, // CROSS_UP for up crosses,CROSS_DOWN for down crosses, CROSS_ALL for all crosses double emptyValueUsed) // The value used for "empty" mark { // finding out the loop direction and step int di = -1; if (endIndex > startIndex) di = 1; // brushing for (int i = startIndex; (i >= startIndex && i <= endIndex) || (i >= endIndex && i <= startIndex); i += di) { // to check the extremum we need at least 1 older bars // if they are not available, there is no reason to continue if (i + 1 >= Bars) { continue; } // check empty values if ( values1[i] == emptyValueUsed || values1[i + 1] == emptyValueUsed || values2[i] == emptyValueUsed || values2[i + 1] == emptyValueUsed || values1[i] == EMPTY_VALUE || values1[i + 1] == EMPTY_VALUE || values2[i] == EMPTY_VALUE || values2[i + 1] == EMPTY_VALUE ) { continue; } // cleaning current value of marking buffer if (di < 0) crosses[i] = EMPTY_VALUE; // cross condition -- simple case if ((values1[i] - values2[i])*(values1[i + 1] - values2[i + 1]) < 0 && (values1[i] - values2[i])*direction >= 0) { crosses[i] = values2[i]; continue; } // cross condition -- complicated case if (values1[i + 1] == values2[i + 1] && values1[i] != values2[i] && (values1[i] - values2[i])*direction >= 0) { // we have potential cross -- let's check it // we find the 2nd end for this int index = i + 1; bool found = false; while ( index < Bars && values1[index] != emptyValueUsed && values1[index] != EMPTY_VALUE && values2[index] != emptyValueUsed && values2[index] != EMPTY_VALUE) { if (values1[index] != values2[index]) { // got it found = true; break; } index++; } if (!found) { // we have an empty value or history end // both cases mean we haven't cross continue; } // test the cross if ((values1[i] - values2[i])*(values1[index] - values2[index]) < 0) { // got the cross crosses[i] = values2[i]; } // else -- got touching } } } // ==================================================== // Mark for level crosses // ==================================================== void MarkLevelCrosses( double values[], // Values of the indicator double level, // Level value for a cross check double& crosses[], // Buffer for the crosses int startIndex, // Start index for check (it included) int endIndex, // End index for check (it included) int direction, // CROSS_UP for up crosses,CROSS_DOWN for down crosses, CROSS_ALL for all crosses double emptyValueUsed) // The value used for "empty" mark { // finding out the loop direction and step int di = -1; if (endIndex > startIndex) di = 1; // brushing for (int i = startIndex; (i >= startIndex && i <= endIndex) || (i >= endIndex && i <= startIndex); i += di) { // to check the extremum we need at least 1 older bars // if they are not available, there is no reason to continue if (i + 1 >= Bars) { continue; } // checking empty values if ( values[i] == emptyValueUsed || values[i + 1] == emptyValueUsed || values[i] == EMPTY_VALUE || values[i + 1] == EMPTY_VALUE ) { continue; } // clean current value if (di < 0) crosses[i] = EMPTY_VALUE; // check the cross -- simple case if ((values[i] - level)*(values[i + 1] - level) < 0 && (values[i] - level)*direction >= 0) { crosses[i] = level; continue; } // check the cross -- complicated case if (values[i + 1] == level && values[i] != level && (values[i] - level)*direction >= 0) { // we have potential cross -- let's check it // we find the 2nd end for this int index = i + 1; bool found = false; while ( index < Bars && values[index] != emptyValueUsed && values[index] != EMPTY_VALUE) { if (values[index] != level) { // got it found = true; break; } index++; } if (!found) { // we have an empty value or history end // both cases mean we haven't cross continue; } // test the cross if ((values[i] - level)*(values[index] - level) < 0) { // got the cross crosses[i] = level; } // else got touching } } } // ==================================================== // Mark for levels // ==================================================== void MarkLevel( double values[], // Values of the indicator double& level[], // Buffer for the crosses int startIndex, // Start index for check (it included) int endIndex, // End index for check (it included) double levelValue, // Level value int condition, // Mark condition (LESS_THAN = -1, GREATER_THAN = 1) double emptyValueUsed) // The value used for "empty" mark { int Depth = 2; // look 1 bar more in order not to leave garbage marks in marking buffer if (endIndex > startIndex) { endIndex = MathMax(endIndex, Depth); } else { startIndex = MathMax(startIndex, Depth); } // finding out the loop direction and step int di = -1; if (endIndex > startIndex) di = 1; // brushing for (int i = startIndex; (i >= startIndex && i <= endIndex) || (i >= endIndex && i <= startIndex); i += di) { if (values[i] == EMPTY_VALUE || values[i] == emptyValueUsed) { continue; } if (di < 0) level[i] = EMPTY_VALUE; // over the level if ((values[i] - levelValue)*condition >= 0) { level[i] = values[i]; // previous isn't over the level if ((values[i + 1] - levelValue)*condition < 0 && values[i + 1] != emptyValueUsed && values[i + 1] != EMPTY_VALUE) { // mark it too with the value of level level[i + 1] = levelValue; } } // current isn't over the level else { // previous over level if ((values[i + 1] - levelValue)*condition >= 0 && values[i + 1] != EMPTY_VALUE && values[i + 1] != emptyValueUsed) { // mark current with level value level[i] = levelValue; } } } } // ==================================================== // Mark for dynamic levels // ==================================================== void MarkDynamicLevel( double values[], // Values of the indicator double dynamicLevel[], // Dynamical level values for check double& level[], // Buffer for the crosses int startIndex, // Start index for check (it included) int endIndex, // End index for check (it included) int condition, // less (LESS_THAN = -1) or grater than level (GREATER_THAN = 1) double emptyValueUsed) // The value used for "empty" mark { int Depth = 2; // look 1 bar more in order not to leave garbage marks in marking buffer if (endIndex > startIndex) { endIndex = MathMax(endIndex, Depth); } else { startIndex = MathMax(startIndex, Depth); } // finding out the loop direction and step int di = -1; if (endIndex > startIndex) di = 1; // brushing for (int i = startIndex; (i >= startIndex && i <= endIndex) || (i >= endIndex && i <= startIndex); i += di) { if (values[i] == EMPTY_VALUE || values[i] == emptyValueUsed) { continue; } if (di < 0) level[i] = EMPTY_VALUE; // current over level if ((values[i] - dynamicLevel[i])*condition >= 0) { level[i] = values[i]; // previous isn't over the level if ((values[i + 1] - dynamicLevel[i + 1])*condition < 0 && values[i + 1] != emptyValueUsed && values[i + 1] != EMPTY_VALUE) { // mark it too with the value of level level[i + 1] = dynamicLevel[i + 1]; } } // current isn't over the level else { // previous over level if ((values[i + 1] - dynamicLevel[i + 1])*condition >= 0 && values[i + 1] != EMPTY_VALUE && values[i + 1] != emptyValueUsed) { // mark current with level value level[i] = dynamicLevel[i]; } } } } // ==================================================== // Mark for direction (upward) // ==================================================== void MarkGrowing( double values[], // Values of the indicator double& growing1[], // The first buffer to mark the direction double& growing2[], // The second buffer to mark the direction int startIndex, // Start index for check (it included) int endIndex, // End index for check (it included) double emptyValueUsed) // The value used for "empty" mark { // finding out the loop direction and step int di = -1; if (endIndex > startIndex) di = 1; // Marking growing leveks -- reducing levels will be marked as different from growing for (int i = startIndex; (i >= startIndex && i <= endIndex) || (i >= endIndex && i <= startIndex); i += di) { // to check we need at least 2 older bars // if they are not available, there is no reason to continue if (i + 1 >= Bars) { continue; } // checking empty values if ( values[i] == emptyValueUsed || values[i + 1] == emptyValueUsed || values[i] == EMPTY_VALUE || values[i + 1] == EMPTY_VALUE ) { continue; } // cleaning current marks if (di < 0) growing1[i] = EMPTY_VALUE; if (di < 0) growing2[i] = EMPTY_VALUE; // if is growing if (values[i] > values[i + 1]) { // and was growing at previous bar if (values[i + 1] > values[i + 2]) { // mark it growing if (growing1[i + 1] != EMPTY_VALUE) growing1[i] = values[i]; else growing2[i] = values[i]; } // and was not growing at previous bar else { // mark i growing in a free buffer // (it should be at least 1 free) if (growing2[i + 2] == EMPTY_VALUE) { growing2[i] = values[i]; growing2[i + 1] = values[i + 1]; } else { growing1[i] = values[i]; growing1[i + 1] = values[i + 1]; } } } // cleaning tail if necessary else if (i == 0) { if (growing1[i + 1] != EMPTY_VALUE && growing1[i + 2] == EMPTY_VALUE) { growing1[i + 1] = EMPTY_VALUE; } if (growing2[i + 1] != EMPTY_VALUE && growing2[i + 2] == EMPTY_VALUE) { growing2[i + 1] = EMPTY_VALUE; } } } } // ==================================================== // Mark for direction (downward) // ==================================================== void MarkReducing( double values[], // Values of the indicator double& reducing1[], // The first buffer to mark the direction double& reducing2[], // The second buffer to mark the direction int startIndex, // Start index for check (it included) int endIndex, // End index for check (it included) double emptyValueUsed) // The value used for "empty" mark { // finding out the loop direction and step int di = -1; if (endIndex > startIndex) di = 1; // marking reducing levels for (int i = startIndex; (i >= startIndex && i <= endIndex) || (i >= endIndex && i <= startIndex); i += di) { // to check we need at least 2 older bars // if they are not available, there is no reason to continue if (i + 1 >= Bars) { continue; } // checking empty values if ( values[i] == emptyValueUsed || values[i + 1] == emptyValueUsed || values[i] == EMPTY_VALUE || values[i + 1] == EMPTY_VALUE ) { continue; } // cleaning current marks if (di < 0) reducing1[i] = EMPTY_VALUE; if (di < 0) reducing2[i] = EMPTY_VALUE; // is reducing if (values[i] < values[i + 1]) { // and was reducing at previous bar if (values[i + 1] < values[i + 2]) { // mark it in current mark buffer if (reducing1[i + 1] != EMPTY_VALUE) reducing1[i] = values[i]; else reducing2[i] = values[i]; } // and was not reducing at previous bar else { // mark it in a free mark buffer if (reducing2[i + 2] == EMPTY_VALUE) { reducing2[i] = values[i]; reducing2[i + 1] = values[i + 1]; } else { reducing1[i] = values[i]; reducing1[i + 1] = values[i + 1]; } } } // cleaning tail if necessary else if (i == 0) { if (reducing1[i + 1] != EMPTY_VALUE && reducing1[i + 2] == EMPTY_VALUE) { reducing1[i + 1] = EMPTY_VALUE; } if (reducing2[i + 1] != EMPTY_VALUE && reducing2[i + 2] == EMPTY_VALUE) { reducing2[i + 1] = EMPTY_VALUE; } } } } если на предыдущем баре не падало else { // пишем в буфер который не использовался последние 2 бара // (1 такой должен быть обязательно) if (reducing2[i + 2] == EMPTY_VALUE) { reducing2[i] = values[i]; reducing2[i + 1] = values[i + 1]; } else { reducing1[i] = values[i]; reducing1[i + 1] = values[i + 1]; } } } // удаление раскраски хвостика если не растет else if (i == 0) { if (reducing1[i + 1] != EMPTY_VALUE && reducing1[i + 2] == EMPTY_VALUE) { reducing1[i + 1] = EMPTY_VALUE; } if (reducing2[i + 1] != EMPTY_VALUE && reducing2[i + 2] == EMPTY_VALUE) { reducing2[i + 1] = EMPTY_VALUE; } } } }