Skip to main content

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.

This lesson uses the Current HyperionX.Custom.Strategies.Strategy runtime and its managed-order helpers. Keep the Strategy And Order Reference open while working; another platform's method names and order lifecycle are not interchangeable with HyperionX.

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(0, "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: Managed Limit Entry

Use the managed limit-entry helper for ordinary limit orders. Keep the returned order so stale working entries can still be cancelled.

private Order _entryOrder;
private int _entryOrderBar = -1;

private void PlaceLongLimit(double limitPrice)
{
_entryOrder = EnterLongLimit(1, limitPrice, "Long Limit");
_entryOrderBar = CurrentBar;
}

private void CancelStaleEntry()
{
if (_entryOrder == null)
return;

if (CurrentBar - _entryOrderBar >= 3)
{
CancelOrder(_entryOrder);
_entryOrder = null;
_entryOrderBar = -1;
}
}

Managed mode handles common order registration; it does not remove the need to cancel stale working entries.

Lesson 5: Managed Stop Entry

Stop entries are for breakout logic.

double breakoutPrice = High[1] + TickSize;
EnterLongStopMarket(1, breakoutPrice, "Breakout Long");

Use the corresponding managed short, limit, and stop helpers for ordinary entry variants. Reserve direct orders for advanced unmanaged workflows that need custom OCO, partial-fill, or explicit order-state control.

Lesson 6: Fixed Exits

Begin with managed exits:

SetStopLossTicks("MA Cross Long", 20);
SetProfitTargetTicks("MA Cross Long", 40);

Use direct SubmitOrder exits only for advanced unmanaged workflows such as custom OCO groups, scale-outs, partial exits, or custom order state. Such workflows must handle order updates, cancellation, rejection, partial fills, and OCO recovery explicitly and must be tested in simulation.

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.
  • The strategy is tested first with an explicitly selected LocalPaper account. Playback does not change the selection automatically, and the current release-candidate build rejects Broker and Server Paper order mutations while Playback is active.

For historical-model limitations and the current clean-installer research blocker, continue with Backtesting and Validation.