Skip to content

Commit

Permalink
OrderQuery: Adds CalcSumByPropWithCond() and FindPropBySum()
Browse files Browse the repository at this point in the history
  • Loading branch information
kenorb committed Oct 2, 2021
1 parent c12f665 commit 564f5f9
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 0 deletions.
48 changes: 48 additions & 0 deletions OrderQuery.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ class OrderQuery : public Dynamic {
/**
* Calculates sum of order's value based on the property's enum.
*
* @param
* _prop Order's property to sum by (e.g. ORDER_PROP_PROFIT).
*
* @return
* Returns sum of order's values.
*/
Expand All @@ -65,6 +68,24 @@ class OrderQuery : public Dynamic {
return _sum;
}

/**
* Calculates sum of order's value based on the property's enum with condition.
*
* @return
* Returns sum of order's values based on the condition.
*/
template <typename E, typename ECT, typename ECV, typename T>
T CalcSumByPropWithCond(E _prop, ECT _prop_cond_type, ECV _prop_cond_value) {
T _sum = 0;
for (DictStructIterator<long, Ref<Order>> iter = orders.Begin(); iter.IsValid(); ++iter) {
Order *_order = iter.Value().Ptr();
if (_order.Get<ECV>(_prop_cond_type) == _prop_cond_value) {
_sum += _order.Get<T>(_prop);
}
}
return _sum;
}

/**
* Find order by comparing property's value given the comparison operator.
*
Expand Down Expand Up @@ -111,6 +132,33 @@ class OrderQuery : public Dynamic {
return _order_ref_found;
}

/**
* Find property enum with the highest sum based on another property's enums.
*
* For example, you can find order's type which has the highest profit.
*
* @param
* _props Array of properties to group the sums by.
* _prop_sum Order's property to sum by (e.g. ORDER_PROP_PROFIT).
*
* @return
* Returns property enum having the highest sum.
*/
template <typename EP, typename ES, typename ECT, typename T>
EP FindPropBySum(ARRAY_REF(EP, _props), ES _prop_sum, ECT _prop_sum_type,
STRUCT_ENUM(OrderQuery, ORDER_QUERY_OP) _op = STRUCT_ENUM(OrderQuery, ORDER_QUERY_OP_GT)) {
EP _peak_type = _props[0];
T _peak_sum = CalcSumByPropWithCond<ES, ECT, EP, T>(_prop_sum, _prop_sum_type, _peak_type);
for (int _i = 1; _i < ArraySize(_props); _i++) {
T _sum = CalcSumByPropWithCond<ES, ECT, EP, T>(_prop_sum, _prop_sum_type, _props[_i]);
if (Compare(_sum, _op, _peak_sum)) {
_peak_sum = _sum;
_peak_type = _props[_i];
}
}
return _peak_type;
}

/**
* Perform a comparison operation on two values.
*
Expand Down
19 changes: 19 additions & 0 deletions tests/OrderQueryTest.mq5
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ bool Test01() {
for (int i = -10; i <= 10; i++) {
OrderData _odata;
_odata.Set<float>(ORDER_PROP_PROFIT, (float)i);
_odata.Set(ORDER_TYPE, i % 2 == 0 ? ORDER_TYPE_BUY : ORDER_TYPE_SELL);
Ref<Order> _order = new Order(_odata);
orders.Push(_order);
}
Expand Down Expand Up @@ -71,6 +72,24 @@ bool Test01() {
assertTrueOrReturnFalse(_order_profit_gt_2.Ptr().Get<float>(ORDER_PROP_PROFIT) > 2,
"Order with profit greater than 2 not found!");

// Calculate profit sums (all, buys and sells).
float _order_profit_all = _oquery.CalcSumByProp<ENUM_ORDER_PROPERTY_CUSTOM, float>(ORDER_PROP_PROFIT);
assertTrueOrReturnFalse(_order_profit_all == 0, "All profit should be 0!");
float _order_profit_buy =
_oquery.CalcSumByPropWithCond<ENUM_ORDER_PROPERTY_CUSTOM, ENUM_ORDER_PROPERTY_INTEGER, ENUM_ORDER_TYPE, float>(
ORDER_PROP_PROFIT, ORDER_TYPE, ORDER_TYPE_BUY);
float _order_profit_sell =
_oquery.CalcSumByPropWithCond<ENUM_ORDER_PROPERTY_CUSTOM, ENUM_ORDER_PROPERTY_INTEGER, ENUM_ORDER_TYPE, float>(
ORDER_PROP_PROFIT, ORDER_TYPE, ORDER_TYPE_SELL);
assertTrueOrReturnFalse(_order_profit_buy == _order_profit_sell, "Profit of buys should equal profit of sells!");

// Find order type with the highest profit.
ENUM_ORDER_TYPE _order_types[] = {ORDER_TYPE_BUY, ORDER_TYPE_SELL};
ENUM_ORDER_TYPE _order_type_highest_profit =
_oquery.FindPropBySum<ENUM_ORDER_TYPE, ENUM_ORDER_PROPERTY_CUSTOM, ENUM_ORDER_PROPERTY_INTEGER, float>(
_order_types, ORDER_PROP_PROFIT, ORDER_TYPE);
assertTrueOrReturnFalse(_order_type_highest_profit == 0.0f, "Highest profitable order type incorrect!");

//_order_profit_best.ToString(); // @todo
//_order_profit_worst.ToString(); // @todo
return _result;
Expand Down

0 comments on commit 564f5f9

Please sign in to comment.