191 lines
6.9 KiB
MQL5
191 lines
6.9 KiB
MQL5
#ifndef PRICE_SPEEDOMETER_MQH
|
|
#define PRICE_SPEEDOMETER_MQH
|
|
|
|
#include "circular_buffer.mqh"
|
|
|
|
class Price_speedometer {
|
|
protected:
|
|
Circular_buffer<MqlTick> ticks;
|
|
const int period_in_ticks;
|
|
const long period_in_milliseconds;
|
|
double speed_per_ticks;
|
|
double directional_speed_per_ticks;
|
|
double percent_per_ticks;
|
|
double speed_per_milliseconds;
|
|
double directional_speed_per_milliseconds;
|
|
double percent_per_milliseconds;
|
|
|
|
public:
|
|
Price_speedometer(const int &_ticks_capacity, const int &_period_in_ticks,
|
|
const long &_period_in_milliseconds)
|
|
: ticks(_ticks_capacity), period_in_ticks(_period_in_ticks),
|
|
period_in_milliseconds(_period_in_milliseconds), speed_per_ticks(0.0),
|
|
directional_speed_per_ticks(0.0), percent_per_ticks(0.0),
|
|
speed_per_milliseconds(0.0), directional_speed_per_milliseconds(0.0),
|
|
percent_per_milliseconds(0.0) {}
|
|
|
|
Price_speedometer(const Price_speedometer &_price_speedometer)
|
|
: ticks(_price_speedometer.ticks),
|
|
period_in_ticks(_price_speedometer.period_in_ticks),
|
|
period_in_milliseconds(_price_speedometer.period_in_milliseconds),
|
|
speed_per_ticks(_price_speedometer.speed_per_ticks),
|
|
directional_speed_per_ticks(
|
|
_price_speedometer.directional_speed_per_ticks),
|
|
percent_per_ticks(_price_speedometer.percent_per_ticks),
|
|
speed_per_milliseconds(_price_speedometer.speed_per_milliseconds),
|
|
directional_speed_per_milliseconds(
|
|
_price_speedometer.directional_speed_per_milliseconds),
|
|
percent_per_milliseconds(_price_speedometer.percent_per_milliseconds) {}
|
|
|
|
virtual ~Price_speedometer() {}
|
|
|
|
public:
|
|
Price_speedometer operator=(const Price_speedometer &_price_speedometer) {
|
|
ticks = _price_speedometer.ticks;
|
|
speed_per_ticks = _price_speedometer.speed_per_ticks;
|
|
directional_speed_per_ticks =
|
|
_price_speedometer.directional_speed_per_ticks;
|
|
percent_per_ticks = _price_speedometer.percent_per_ticks;
|
|
speed_per_milliseconds = _price_speedometer.speed_per_milliseconds;
|
|
directional_speed_per_milliseconds =
|
|
_price_speedometer.directional_speed_per_milliseconds;
|
|
percent_per_milliseconds = _price_speedometer.percent_per_milliseconds;
|
|
return *this;
|
|
}
|
|
|
|
protected:
|
|
double calculate_price_speed(const int &_period_in_ticks) const {
|
|
double price_change = 0.0;
|
|
const int ticks_size = ticks.get_size();
|
|
int position_offset =
|
|
(int)MathMin((double)(_period_in_ticks - 1), (double)(ticks_size - 1));
|
|
for (position_offset; position_offset > 0; --position_offset) {
|
|
MqlTick previous_tick = {0ul, 0.0, 0.0, 0.0, 0ul, 0l, 0u, 0.0};
|
|
bool return_value = ticks.read(position_offset, previous_tick);
|
|
if (!return_value || previous_tick.time_msc == 0l) {
|
|
continue;
|
|
}
|
|
MqlTick next_tick = {0ul, 0.0, 0.0, 0.0, 0ul, 0l, 0u, 0.0};
|
|
return_value = ticks.read(position_offset - 1, next_tick);
|
|
if (!return_value || next_tick.time_msc == 0l) {
|
|
continue;
|
|
}
|
|
price_change += MathAbs(next_tick.last - previous_tick.last);
|
|
}
|
|
return price_change;
|
|
}
|
|
|
|
double calculate_directional_price_speed(const int &_period_in_ticks) const {
|
|
if (_period_in_ticks < 2) {
|
|
return 0.0;
|
|
}
|
|
const int ticks_size = ticks.get_size();
|
|
const int first_position_offset =
|
|
(int)MathMin((double)(_period_in_ticks - 1), (double)(ticks_size - 1));
|
|
MqlTick first_tick = {0ul, 0.0, 0.0, 0.0, 0ul, 0l, 0u, 0.0};
|
|
bool return_value = ticks.read(first_position_offset, first_tick);
|
|
if (!return_value || first_tick.time_msc == 0l) {
|
|
return 0.0;
|
|
}
|
|
const int last_position_offset = 0;
|
|
MqlTick last_tick = {0ul, 0.0, 0.0, 0.0, 0ul, 0l, 0u, 0.0};
|
|
return_value = ticks.read(last_position_offset, last_tick);
|
|
if (!return_value || last_tick.time_msc == 0l) {
|
|
return 0.0;
|
|
}
|
|
return last_tick.last - first_tick.last;
|
|
}
|
|
|
|
int find_position_offset(const long &_period_in_milliseconds) const {
|
|
const int ticks_size = ticks.get_size();
|
|
if (ticks_size < 2) {
|
|
return 0;
|
|
}
|
|
const int last_position_offset = 0;
|
|
MqlTick last_tick = {0ul, 0.0, 0.0, 0.0, 0ul, 0l, 0u, 0.0};
|
|
const bool return_value = ticks.read(last_position_offset, last_tick);
|
|
if (!return_value || last_tick.time_msc == 0l) {
|
|
return 0;
|
|
}
|
|
int previous_position_offset = 1;
|
|
MqlTick previous_tick = {0ul, 0.0, 0.0, 0.0, 0ul, 0l, 0u, 0.0};
|
|
while (ticks.read(previous_position_offset, previous_tick)) {
|
|
if (previous_tick.time_msc <
|
|
last_tick.time_msc - _period_in_milliseconds) {
|
|
break;
|
|
}
|
|
++previous_position_offset;
|
|
}
|
|
return previous_position_offset - 1;
|
|
}
|
|
|
|
public:
|
|
double get_speed_per_ticks() const { return speed_per_ticks; }
|
|
|
|
double get_directional_speed_per_ticks() const {
|
|
return directional_speed_per_ticks;
|
|
}
|
|
|
|
double get_percent_per_ticks() const { return percent_per_ticks; }
|
|
|
|
double get_speed_per_milliseconds() const { return speed_per_milliseconds; }
|
|
|
|
double get_directional_speed_per_milliseconds() const {
|
|
return directional_speed_per_milliseconds;
|
|
}
|
|
|
|
double get_percent_per_milliseconds() const {
|
|
return percent_per_milliseconds;
|
|
}
|
|
|
|
void add_tick(const MqlTick &tick) {
|
|
ticks.write(tick);
|
|
return;
|
|
}
|
|
|
|
void calculate_price_speeds() {
|
|
speed_per_ticks = calculate_price_speed(period_in_ticks);
|
|
directional_speed_per_ticks =
|
|
calculate_directional_price_speed(period_in_ticks);
|
|
const int period_in_milliseconds_in_ticks =
|
|
find_position_offset(period_in_milliseconds) + 1;
|
|
speed_per_milliseconds =
|
|
calculate_price_speed(period_in_milliseconds_in_ticks);
|
|
directional_speed_per_milliseconds =
|
|
calculate_directional_price_speed(period_in_milliseconds_in_ticks);
|
|
return;
|
|
}
|
|
|
|
void calculate_percents() {
|
|
percent_per_ticks = 0.0;
|
|
if (speed_per_ticks != 0.0) {
|
|
percent_per_ticks = directional_speed_per_ticks / speed_per_ticks * 100.0;
|
|
}
|
|
percent_per_milliseconds = 0.0;
|
|
if (speed_per_milliseconds != 0.0) {
|
|
percent_per_milliseconds =
|
|
directional_speed_per_milliseconds / speed_per_milliseconds * 100.0;
|
|
}
|
|
return;
|
|
}
|
|
|
|
string get_comment() const {
|
|
const int digits = _Digits;
|
|
const string comment =
|
|
"Per " + IntegerToString((long)period_in_ticks) +
|
|
" ticks:\nSpeed: " +
|
|
DoubleToString(speed_per_ticks, digits) + "\nDirectional speed: " +
|
|
DoubleToString(directional_speed_per_ticks, digits) +
|
|
"\nPercent: " + IntegerToString((long)percent_per_ticks) +
|
|
"%\n\nPer " + IntegerToString(period_in_milliseconds) +
|
|
" ms:\nSpeed: " +
|
|
DoubleToString(speed_per_milliseconds, digits) +
|
|
"\nDirectional speed: " +
|
|
DoubleToString(directional_speed_per_milliseconds, digits) +
|
|
"\nPercent: " +
|
|
IntegerToString((long)percent_per_milliseconds) + "%";
|
|
return comment;
|
|
}
|
|
};
|
|
|
|
#endif
|