2025-12-13 12:04:25 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| ConstantPartial.mqh |
|
| | | //| Copyright 2025, Niquel Mendoza. |
|
| | | //| https://www.mql5.com/es/users/nique_372/news |
|
| | | //+------------------------------------------------------------------+
|
| | | #property copyright "Copyright 2025, Niquel Mendoza."
|
| | | #property link "https://www.mql5.com/es/users/nique_372/news"
|
| | | #property strict
|
| | |
|
| | | #ifndef MQLARTICLES_POSMGMT_CONDPARTIALS_BASE_CONSTPARTIALS_MQH
|
| | | #define MQLARTICLES_POSMGMT_CONDPARTIALS_BASE_CONSTPARTIALS_MQH
|
| | |
|
2026-09-13 08:47:52 -05:00 | | |
|
2025-12-13 12:04:25 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| Include |
|
| | | //+------------------------------------------------------------------+
|
| | | #include "Base.mqh"
|
| | |
|
2026-09-13 08:47:52 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | namespace TSN
|
| | | {
|
2025-12-13 12:04:25 -05:00 | | | //+---------------------------------------------------------------------+
|
| | | //| Class for implementing constant partial closes. |
|
| | | //| (A single percentage that will be closed partially from the trade) |
|
| | | //+---------------------------------------------------------------------+
|
| | | class CConditionalPartialsConst : public CConditionalPartials
|
| | | {
|
| | | private:
|
| | | // Variable that indicates to the class if it should force the trade close even if the lot to be partially closed
|
| | | // is less than the minimum volume
|
| | | bool m_forze_to_close;
|
| | |
|
2026-08-04 17:02:36 -05:00 | | | //---
|
2025-12-13 12:04:25 -05:00 | | | void ClosePartialsForBuyPositions() override;
|
| | | void ClosePartialsForSellPositions() override;
|
| | |
|
2025-12-21 21:53:59 -05:00 | | | public:
|
2026-01-31 19:44:40 -05:00 | | | CConditionalPartialsConst() : m_forze_to_close(false) {}
|
2025-12-21 21:53:59 -05:00 | | |
|
2025-12-13 12:04:25 -05:00 | | | //--- Force to close setter and getter
|
| | | bool ForzeToClose() const { return m_forze_to_close; }
|
| | | void ForzeToClose(bool new_val) { m_forze_to_close = new_val; }
|
| | | };
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Function that iterates over all positions to track (buy) |
|
| | | //| and partially closes the trade |
|
| | | //+------------------------------------------------------------------+
|
| | | void CConditionalPartialsConst::ClosePartialsForBuyPositions(void)
|
| | | {
|
| | | //--- Resize to zero
|
2026-08-04 17:02:36 -05:00 | | | m_indexes_to_remove_s = 0;
|
| | |
|
| | | //---
|
| | | MQLARTICLES_CPARTIALES_CHECK_RESIZE_IR
|
2025-12-13 12:04:25 -05:00 | | |
|
| | | //--- Iteration
|
| | | for(int i = 0; i < m_tracked_positions_size; i++)
|
| | | {
|
| | | if(m_tracked_positions_arr[i].type == POSITION_TYPE_SELL || m_symbol_bid < m_tracked_positions_arr[i].next_min_price)
|
| | | continue;
|
| | |
|
| | | if(!::PositionSelectByTicket(m_tracked_positions_arr[i].ticket))
|
| | | {
|
| | | // "Delete"
|
2026-08-04 17:02:36 -05:00 | | | m_indexes_to_remove[m_indexes_to_remove_s++] = i;
|
2025-12-13 12:04:25 -05:00 | | | #ifdef CONDITIONAL_PARTIAL_CONST_MORE_INFO
|
| | | LogError(::StringFormat("Ticket selection failed %I64u", m_tracked_positions_arr[i].ticket), FUNCION_ACTUAL);
|
| | | #endif
|
| | | continue;
|
| | | }
|
| | |
|
| | | //---
|
| | | m_tracked_positions_arr[i].next_min_price += m_min_distance_value;
|
| | |
|
| | | //--- Initial calculation
|
| | | const double lot_size = ::PositionGetDouble(POSITION_VOLUME);
|
| | | double volume_to_close = m_volumes_to_close_arr[0] * lot_size;
|
| | |
|
| | | //--- Check min volume to close
|
| | | if(volume_to_close < m_symbol_min_volume)
|
| | | {
|
| | | if(m_forze_to_close)
|
| | | {
|
| | | volume_to_close = lot_size;
|
| | | }
|
| | | else
|
| | | {
|
| | | //--- Log
|
| | | LogWarning(::StringFormat("Partial close %d, of position %I64u skipped, volume to close %.*f is less than minimum volume %.*f",
|
| | | 0,
|
| | | m_tracked_positions_arr[i].ticket,
|
| | | m_symbol_digits,
|
| | | volume_to_close,
|
| | | m_symbol_digits,
|
| | | m_symbol_min_volume), FUNCION_ACTUAL);
|
| | |
|
| | | //--- "Delete"
|
2026-08-04 17:02:36 -05:00 | | | m_indexes_to_remove[m_indexes_to_remove_s++] = i;
|
2025-12-13 12:04:25 -05:00 | | | continue;
|
| | | }
|
| | | }
|
| | |
|
| | | //--- Round
|
| | | volume_to_close = RoundToStep(volume_to_close, m_symbol_volume_step);
|
| | |
|
| | | #ifdef CONDITIONAL_PARTIAL_CONST_MORE_INFO
|
| | | LogInfo(::StringFormat("Partially closing %.2f lots of position %I64u", volume_to_close, m_tracked_positions_arr[i].ticket), FUNCION_ACTUAL);
|
| | | #endif
|
| | |
|
| | | //--- Close
|
| | | m_trade.PositionClosePartial(m_tracked_positions_arr[i].ticket, volume_to_close);
|
| | | }
|
| | |
|
| | | //--- Multiple remove
|
2026-08-04 17:02:36 -05:00 | | | RemoveMultipleIndexesWithVSizeRemoveCts(m_tracked_positions_arr, m_tracked_positions_size, m_indexes_to_remove,
|
| | | 0, m_indexes_to_remove_s);
|
2025-12-13 12:04:25 -05:00 | | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Function that iterates over all positions to track (sell) |
|
| | | //| and partially closes the trade |
|
| | | //+------------------------------------------------------------------+
|
| | | void CConditionalPartialsConst::ClosePartialsForSellPositions(void)
|
| | | {
|
| | | //--- Resize to zero
|
2026-08-04 17:02:36 -05:00 | | | m_indexes_to_remove_s = 0;
|
| | |
|
| | | //---
|
| | | MQLARTICLES_CPARTIALES_CHECK_RESIZE_IR
|
2025-12-13 12:04:25 -05:00 | | |
|
| | | //--- Iteration
|
| | | for(int i = 0; i < m_tracked_positions_size; i++)
|
| | | {
|
| | | if(m_tracked_positions_arr[i].type == POSITION_TYPE_BUY || m_symbol_ask > m_tracked_positions_arr[i].next_min_price)
|
| | | continue;
|
| | |
|
| | | if(!::PositionSelectByTicket(m_tracked_positions_arr[i].ticket))
|
| | | {
|
| | | // "Delete"
|
2026-08-04 17:02:36 -05:00 | | | m_indexes_to_remove[m_indexes_to_remove_s++] = i;
|
2025-12-13 12:04:25 -05:00 | | | #ifdef CONDITIONAL_PARTIAL_CONST_MORE_INFO
|
| | | LogError(::StringFormat("Ticket selection failed %I64u", m_tracked_positions_arr[i].ticket), FUNCION_ACTUAL);
|
| | | #endif
|
| | | continue;
|
| | | }
|
| | |
|
| | | //---
|
| | | m_tracked_positions_arr[i].next_min_price -= m_min_distance_value;
|
| | |
|
| | | //--- Initial calculation
|
| | | const double lot_size = ::PositionGetDouble(POSITION_VOLUME);
|
| | | double volume_to_close = m_volumes_to_close_arr[0] * lot_size;
|
| | |
|
| | | //--- Check min volume to close
|
| | | if(volume_to_close < m_symbol_min_volume)
|
| | | {
|
| | | if(m_forze_to_close)
|
| | | {
|
| | | volume_to_close = lot_size;
|
| | | }
|
| | | else
|
| | | {
|
| | | //--- Log
|
| | | LogWarning(::StringFormat("Partial close %d, of position %I64u skipped, volume to close %.*f is less than minimum volume %.*f",
|
| | | 0,
|
| | | m_tracked_positions_arr[i].ticket,
|
| | | m_symbol_digits,
|
| | | volume_to_close,
|
| | | m_symbol_digits,
|
| | | m_symbol_min_volume), FUNCION_ACTUAL);
|
| | |
|
| | | //--- "Delete"
|
2026-08-04 17:02:36 -05:00 | | | m_indexes_to_remove[m_indexes_to_remove_s++] = i;
|
2025-12-13 12:04:25 -05:00 | | | continue;
|
| | | }
|
| | | }
|
| | |
|
| | | //--- Round
|
| | | volume_to_close = RoundToStep(volume_to_close, m_symbol_volume_step);
|
| | |
|
| | | #ifdef CONDITIONAL_PARTIAL_CONST_MORE_INFO
|
| | | LogInfo(::StringFormat("Partially closing %.2f lots of position %I64u", volume_to_close, m_tracked_positions_arr[i].ticket), FUNCION_ACTUAL);
|
| | | #endif
|
| | |
|
| | | //--- Close
|
| | | m_trade.PositionClosePartial(m_tracked_positions_arr[i].ticket, volume_to_close);
|
| | | }
|
| | |
|
| | | //--- Multiple remove
|
2026-08-04 17:02:36 -05:00 | | | RemoveMultipleIndexesWithVSizeRemoveCts(m_tracked_positions_arr, m_tracked_positions_size, m_indexes_to_remove,
|
| | | 0, m_indexes_to_remove_s);
|
2025-12-13 12:04:25 -05:00 | | | }
|
2026-09-13 08:47:52 -05:00 | | | }
|
2025-12-13 12:04:25 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //+------------------------------------------------------------------+
|
| | | #endif // MQLARTICLES_POSMGMT_CONDPARTIALS_BASE_CONSTPARTIALS_MQH
|