No description
Find a file
2026-05-05 09:29:11 -03:00
knitpkg Initial creation 2026-05-04 18:32:03 -03:00
src Docs improved, new test cases, added README and LICENSE 2026-05-05 09:29:11 -03:00
tests Docs improved, new test cases, added README and LICENSE 2026-05-05 09:29:11 -03:00
.gitignore Initial creation 2026-05-04 18:32:03 -03:00
knitpkg.yaml Docs improved, new test cases, added README and LICENSE 2026-05-05 09:29:11 -03:00
LICENSE Docs improved, new test cases, added README and LICENSE 2026-05-05 09:29:11 -03:00
README.md Docs improved, new test cases, added README and LICENSE 2026-05-05 09:29:11 -03:00

riskgate-service-realcase

Gate risk manager service — real scenario use case.

Implements RiskGateHandler from the @douglasrechia/riskgate package as a MetaTrader 5 service that listens on a socket and approves or rejects incoming trade signals based on a set of risk rules.


Risk Rules

Rule Detail
Signal validation Signal must contain symbol, sl_points, and magic; symbol must be non-empty and sl_points must be > 0
Lot sizing 0.5% of account equity (core equity model — closed trades), sized from SL in points
Daily loss limit Daily P&L < −2% of equity → all trades banned until midnight
Daily trade limit Max 6 trades per day (open + closed combined)
Per-symbol limit Max 2 open positions per symbol
Correlated exposure 50% lot reduction when another open position shares the same magic number on a different symbol

Project Structure

src/
  RiskgateServiceRealCase.mq5   # Service entry point — starts the RiskGateServer on port 5555
  RiskgateHandler.mqh           # MyHandler implementation with all risk rules
  RiskgateHandlerDep.mqh        # KnitPkg entrypoint — declares external dependency includes
  AccountInfo.mqh               # IAccountInfo interface + Real/Mock implementations
  TradeHistory.mqh              # ITradeHistory interface + Real/Mock implementations
  OpenPositions.mqh             # IOpenPositions interface + Real/Mock implementations
  SymbolInfo.mqh                # ISymbolInfo interface + Real/Mock implementations
tests/
  UnitTests.mq5                 # Unit tests for MyHandler

How It Works

The service starts a RiskGateServer on port 5555. When a signal arrives, MyHandler.OnSignal() runs the following pipeline:

  1. Signal validation — rejects if required keys are missing or values are invalid (invalid_signal)
  2. Daily stats — computes today's closed P&L and closed position count from trade history
  3. Daily trade limit — rejects if open + closed positions ≥ 6 (daily_max_positions_limit)
  4. Daily loss limit — rejects if today's P&L < −2% of balance (daily_loss_limit)
  5. Per-symbol limit — rejects if ≥ 2 open positions already exist on the same symbol (max_positions_reached)
  6. Lot calculation — sizes lot to 0.5% risk from SL in points; halves it if correlated exposure is detected
  7. Approval — returns approved = true with the calculated lot

Signal format (JSON)

{
  "symbol":    "EURUSD",
  "sl_points": 50,
  "magic":     1
}

Response format (JSON)

{
  "approved": true,
  "lot":      0.05,
  "reason":   ""
}

Possible reason values when approved = false:

  • invalid_signal
  • daily_max_positions_limit
  • daily_loss_limit
  • max_positions_reached
  • lot_too_small

Dependencies

Managed by KnitPkg.

Package Version
@douglasrechia/riskgate ^1.0.0
@douglasrechia/logger ^1.0.0 (transitive)
@douglasrechia/sockets ^1.0.0 (transitive)
@knitpkg-labs/jason ^1.0.0 (transitive)

Install dependencies:

kp install

Build

Compile the service and unit tests:

kp compile

Output binaries are placed in bin/.


Tests

Unit tests are in tests/UnitTests.mq5 and cover MyHandler in isolation using mock implementations of all external dependencies (MockTradeHistory, MockAccountInfo, MockOpenPositions, RealSymbolInfo).

Test Description
Test_ApprovedTrade_LotRisksHalfPercentOfBalance Approves trade and sizes lot to exactly 0.5% risk with no history or open positions
Test_ApprovedTrade_With5OpenPositions Approves trade when 5 positions are open on other symbols
Test_RejectedTrade_With6OpenPositions Rejects when 6 positions are already open (daily_max_positions_limit)
Test_RejectedTrade_With2OpenPositionsOnSameSymbol Rejects when 2 positions are open on the same symbol (max_positions_reached)
Test_ApprovedTrade_LotHalvedWithCorrelatedExposure Approves and halves lot when a correlated position (same magic, different symbol) exists
Test_ApprovedTrade_DailyLossUnder2Percent Approves when daily loss is below the 2% threshold
Test_RejectedTrade_DailyLossOver2Percent Rejects when daily loss exceeds the 2% threshold (daily_loss_limit)
Test_RejectedTrade_InvalidSignal_MissingSymbol Rejects signal missing the symbol key (invalid_signal)
Test_RejectedTrade_InvalidSignal_SlPointsZero Rejects signal with sl_points = 0 (invalid_signal)

License

This project is released under the MIT License. See LICENSE for details.


Disclaimer

This code is provided as-is, for educational purposes only.
No warranty (express or implied) is provided. Use at your own risk.