HX103 Strategies
HX103 converts the strategy lessons into HyperionX's order model. The sequence is market entry, limit entry, stop entry, filters, fixed exits, dynamic exits, conditional exits, then a complete modular system.
Lesson 1: Clean Strategy Shape
Keep strategy logic in modules:
OnBarUpdate
-> EntryModule
-> FilterModule
-> ExitModule
-> RiskModule
This prevents one large OnBarUpdate() method from becoming impossible to debug.
Lesson 2: Market Entry
Use managed helpers first. They are easier to read and let HyperionX handle common order registration.
using System.ComponentModel.DataAnnotations;
using HyperionX.Core.Attributes;
using HyperionX.Core.Enums;
using HyperionX.Core.Market;
using HyperionX.Custom.Indicators;
namespace HyperionX.Custom.Strategies;
public class HXMaCrossCourse : Strategy
{
private SMA _fast;
private SMA _slow;
[HyperionXProperty]
[Display(Name = "Fast Period", GroupName = "Entry", Order = 0)]
public int FastPeriod { get; set; }
[HyperionXProperty]
[Display(Name = "Slow Period", GroupName = "Entry", Order = 1)]
public int SlowPeriod { get; set; }
[HyperionXProperty]
[Display(Name = "Quantity", GroupName = "Risk", Order = 0)]
public double Quantity { get; set; }
public override void OnStateChanged()
{
if (State == State.SetDefaults)
{
Name = "HX MA Cross Course";
Version = "1.0";
FastPeriod = 9;
SlowPeriod = 21;
Quantity = 1;
IsManagedOrderMode = true;
}
else if (State == State.Configured)
{
_fast = SMA(FastPeriod);
_slow = SMA(SlowPeriod);
SetStopLossTicks(20);
SetProfitTargetTicks(40);
}
}
public override void OnBarUpdate()
{
if (CurrentBar < SlowPeriod + 1)
return;
bool crossedUp = _fast[0] > _slow[0] && _fast[1] <= _slow[1];
bool crossedDown = _fast[0] < _slow[0] && _fast[1] >= _slow[1];
if (LastPosition.MarketPosition == MarketPosition.Flat && crossedUp)
EnterLong(Quantity, "MA Cross Long");
if (LastPosition.MarketPosition == MarketPosition.Long && crossedDown)
ExitLong("MA Cross Exit", "MA Cross Long");
}
}
Lesson 3: Filters
Filters should return true when trading is allowed or false when blocked.
private bool PassesTimeFilter()
{
int hour = DateTime[0].Hour;
return hour >= 9 && hour < 16;
}
Call filters before placing an entry order.
Lesson 4: Limit Entry
Limit orders need state and timeout handling.
private Order _entryOrder;
private int _entryOrderBar = -1;
private void PlaceLongLimit(double limitPrice)
{
_entryOrder = SubmitOrder(0, OrderAction.Buy, OrderType.Limit, 1, limitPrice, 0, "", "Long Limit");
_entryOrderBar = CurrentBar;
}
private void CancelStaleEntry()
{
if (_entryOrder == null)
return;
if (CurrentBar - _entryOrderBar >= 3)
{
CancelOrder(_entryOrder);
_entryOrder = null;
_entryOrderBar = -1;
}
}
Lesson 5: Stop Entry
Stop entries are for breakout logic.
double breakoutPrice = High[1] + TickSize;
SubmitOrder(0, OrderAction.Buy, OrderType.StopMarket, 1, 0, breakoutPrice, "", "Breakout Long");
Use direct orders when you need exact order type control.
Lesson 6: Fixed Exits
Begin with managed exits:
SetStopLossTicks("MA Cross Long", 20);
SetProfitTargetTicks("MA Cross Long", 40);
Use direct SubmitOrder exits only when teaching OCO strings, scale-outs, partial exits, or custom order state.
Lesson 7: Dynamic Exits
Dynamic exits change as the trade moves. Keep the rules explicit:
- Break-even trigger.
- Trail trigger.
- Trail distance.
- Whether the stop has already moved.
- The order being replaced.
Completion check:
- Entry logic is separated from filters and exits.
- No duplicate entry is sent while already in a position.
- Limit and stop orders are cancelled when stale.
- State is reset on full exit.
- Every order has a useful signal name.