Skip to main content

Build Your First Strategy

This is the shortest supported path from a blank Code Lab file to a strategy that can submit managed orders. The example is intentionally complete so a developer or AI coding assistant can adapt it without borrowing APIs from another trading platform.

DifficultyTimeApplies to
BeginnerAbout 20 minutesHyperionX 1.1.10 and the documented release-candidate custom runtime
Use LocalPaper

A strategy can place real orders when enabled on an external account. Compile first, then test on a chart with an explicitly selected LocalPaper account. Playback changes market data; it does not select LocalPaper for you.

What You Will Build

The strategy:

  • calculates fast and slow moving averages;
  • enters long or short when they cross;
  • registers a stop loss and profit target before each entry;
  • closes an open position on the opposite cross;
  • exposes editable quantity and risk parameters;
  • prints order-state and execution updates for verification.

This is an API example, not a profitable-trading claim.

1. Create The Strategy File

  1. In HyperionX, open Tools > Code Lab.
  2. Select Strategy as the script type.
  3. Select Blank strategy as the template.
  4. Select New.
  5. Replace the generated source with the complete example below.

Code Lab stores strategy source under:

%USERPROFILE%\Documents\HyperionX\Bin\Custom\Strategies

Keep the class name unique. A duplicate public class anywhere in the custom project can block the entire custom assembly.

2. Use A Complete Managed Strategy

using System.ComponentModel.DataAnnotations;
using HyperionX.Core.Attributes;
using HyperionX.Core.Enums;
using HyperionX.Core.Market;

namespace HyperionX.Custom.Strategies;

public class FirstManagedStrategy : Strategy
{
private const string LongEntry = "Long Entry";
private const string ShortEntry = "Short Entry";

[HyperionXProperty]
[Display(Name = "Fast period", GroupName = "Signals", Order = 1)]
[Range(1, 200)]
public int FastPeriod { get; set; }

[HyperionXProperty]
[Display(Name = "Slow period", GroupName = "Signals", Order = 2)]
[Range(2, 500)]
public int SlowPeriod { get; set; }

[HyperionXProperty]
[Display(Name = "Quantity", GroupName = "Risk", Order = 10)]
[Range(1, 1000)]
public double Quantity { get; set; }

[HyperionXProperty]
[Display(Name = "Stop ticks", GroupName = "Risk", Order = 11)]
[Range(1, 10000)]
public double StopTicks { get; set; }

[HyperionXProperty]
[Display(Name = "Target ticks", GroupName = "Risk", Order = 12)]
[Range(1, 10000)]
public double TargetTicks { get; set; }

public override void OnStateChanged()
{
if (State == State.SetDefaults)
{
Name = "First Managed Strategy";
Version = "1.0";
Calculate = CalculateMode.OnBarClose;
IsManagedOrderMode = true;

FastPeriod = 9;
SlowPeriod = 21;
Quantity = 1;
StopTicks = 20;
TargetTicks = 40;
}
}

public override void OnBarUpdate()
{
if (BarsInProgress != 0 || CurrentBar < SlowPeriod + 1)
return;

double fast = AverageClose(FastPeriod);
double slow = AverageClose(SlowPeriod);
double priorFast = AverageClose(FastPeriod, 1);
double priorSlow = AverageClose(SlowPeriod, 1);

bool crossedUp = priorFast <= priorSlow && fast > slow;
bool crossedDown = priorFast >= priorSlow && fast < slow;

if (Ctx.Position.IsFlat && crossedUp)
{
SetStopLossTicks(LongEntry, StopTicks);
SetProfitTargetTicks(LongEntry, TargetTicks);
EnterLong(Quantity, LongEntry);
}
else if (Ctx.Position.IsFlat && crossedDown)
{
SetStopLossTicks(ShortEntry, StopTicks);
SetProfitTargetTicks(ShortEntry, TargetTicks);
EnterShort(Quantity, ShortEntry);
}
else if (Ctx.Position.MarketPosition == MarketPosition.Long && crossedDown)
{
ExitLong(0, "Long Cross Exit", LongEntry);
}
else if (Ctx.Position.MarketPosition == MarketPosition.Short && crossedUp)
{
ExitShort(0, "Short Cross Exit", ShortEntry);
}
}

public override void OnOrderUpdate(Order order)
{
if (order == null)
return;

Print(
$"ORDER {order.Name}: {order.OrderState}, " +
$"quantity={order.Quantity}, filled={order.FilledQuantity}");
}

public override void OnExecutionUpdate(Order order)
{
if (order == null)
return;

Print(
$"FILL {order.Name}: filled={order.FilledQuantity}, " +
$"price={order.FillPrice}");
}

private double AverageClose(int period, int barsAgo = 0)
{
double sum = 0;

for (int index = barsAgo; index < barsAgo + period; index++)
sum += Close[index];

return sum / period;
}
}

3. Understand The Order Calls

The order sequence is deliberate:

SetStopLossTicks(LongEntry, StopTicks);
SetProfitTargetTicks(LongEntry, TargetTicks);
EnterLong(Quantity, LongEntry);
CallMeaning
SetStopLossTicks("Long Entry", 20)Register protection 20 ticks from the fill for the entry named Long Entry.
SetProfitTargetTicks("Long Entry", 40)Register a target 40 ticks from the fill for that same entry.
EnterLong(1, "Long Entry")Submit a managed market entry for quantity 1.

"Long Entry" is not a comment. It is the relationship key between the entry and its protection. The value must match exactly, including spaces and capitalization.

Do not confuse these two uses of “stop”:

IntentSupported managed call
Enter only after price rises to a breakout levelEnterLongStopMarket(quantity, stopPrice, signalName)
Enter only after price falls to a downside breakout levelEnterShortStopMarket(quantity, stopPrice, signalName)
Protect an entry after it fillsSetStopLoss(...) or SetStopLossTicks(...) before the entry

4. Compile The Complete Custom Project

  1. Save the strategy.
  2. Disable any affected strategy that is already running.
  3. Select Build or Compile Project.
  4. Fix every compile error, including errors in unrelated custom files.
  5. Confirm the build completes successfully.

Code Lab compiles all custom source into one HyperionX.Custom.dll. One broken indicator or duplicate class can prevent this strategy from appearing.

5. Load It On A Test Chart

  1. Open a chart with historical data.
  2. Use the chart's Strategies toolbar button or chart context menu.
  3. Select First Managed Strategy.
  4. Select and verify a LocalPaper account.
  5. Review the instrument, timeframe, quantity, stop ticks, and target ticks.
  6. Enable the strategy.
  7. Keep Orders, Positions, Strategies, and Output visible.

Do not use the main New > Strategy command for a local Code Lab strategy. That command opens the server-provisioned catalog.

After rebuilding, remove and add the strategy again, or reload its owning chart or strategy host. Toggling the old object off and on can keep the old assembly.

6. Verify Behavior

Before changing the signal logic, prove the order lifecycle:

  1. The strategy appears in the chart selector.
  2. It calculates without runtime errors.
  3. At most one entry is submitted for a cross.
  4. The entry signal name is correct.
  5. A stop and target appear after the entry fills.
  6. The stop and target use the intended prices and quantity.
  7. Filling one protective order cancels its OCO peer.
  8. OnOrderUpdate reports submitted, working, filled, cancelled, or rejected states.
  9. OnExecutionUpdate reports actual fills.
  10. Disabling the strategy produces the expected provider-side order and position state.

LocalPaper is a simplified full-fill simulator. Repeat provider-specific tests in the intended paper environment before considering live routing.

Entry And Exit Recipes

Use these inherited managed helpers for ordinary strategies:

// Market entries
EnterLong(1, "Long");
EnterShort(1, "Short");

// Limit entries
EnterLongLimit(1, buyLimitPrice, "Long Limit");
EnterShortLimit(1, sellLimitPrice, "Short Limit");

// Stop-market entries
EnterLongStopMarket(1, buyStopPrice, "Long Breakout");
EnterShortStopMarket(1, sellStopPrice, "Short Breakout");

// Exit the available position quantity; 0 resolves the current quantity.
ExitLong(0, "Exit Long", "Long");
ExitShort(0, "Exit Short", "Short");

For the complete overload list and lower-level order methods, use the Strategy And Order Reference.

Give These Sources To An AI

An AI assistant should read the Markdown versions, in this order:

  1. Build Your First Strategy
  2. Strategy And Order Reference
  3. Strategy Development
  4. Script Troubleshooting

Copy and adapt this prompt:

Read the four HyperionX Markdown pages linked above before writing code.

Build one complete HyperionX Code Lab strategy in namespace
HyperionX.Custom.Strategies that derives from Strategy.

Use only APIs documented on those pages. Prefer inherited managed methods:
EnterLong/EnterShort, their Limit and StopMarket variants, ExitLong/ExitShort,
SetStopLoss or SetStopLossTicks, and SetProfitTarget or
SetProfitTargetTicks. Set protection before its matching entry and use the
exact same signal name. Guard early bars and BarsInProgress. Expose bounded
parameters with HyperionXProperty and Range. Include OnOrderUpdate and
OnExecutionUpdate when order state matters.

Do not use NinjaTrader, QuantConnect, TradingView, broker-SDK, Buy, Sell,
ShortSell, Cover, OnStateChange, OnData, or invented HyperionX methods.
Return one complete compilable .cs file, then list any behavior or provider
assumption that still requires simulation testing.

Strategy rules:
[describe entries, filters, exits, sizing, stop, target, and timeframe here]

If an AI proposes an unfamiliar helper, verify it against the Strategy And Order Reference before compiling.