Skip to main content

Research Extensions

HyperionX separates strategy signals from four reusable research responsibilities: parameter search, result scoring, position sizing, and trading costs.

ExtensionDecidesBase type
OptimizerWhich parameter combinations runOptimizer
Optimization fitnessHow a completed strategy run is rankedOptimizationFitness
Money managementWhat quantity a strategy requestsMoneyManagement
CommissionWhat cost is assigned to a completed tradeCommission

These types do not inherit indicator/strategy series or Ctx. Their inputs come from their own contracts.

Optimizer

An optimizer enumerates parameter values, enqueues each parameter set, and schedules iterations.

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using HyperionX.Core.DataCalc.Optimization;

namespace HyperionX.Custom.Optimizers;

public class GridOptimizer : Optimizer
{
private List<OptimizerParameter> _checked = new();

public override Task OnOptimize()
{
_checked = OptimizerParameters
.Where(parameter => parameter.IsChecked)
.ToList();

foreach (var parameter in _checked)
parameter.ResetValue();

do
{
EnqueueParams();
RunIteration();
}
while (NextParameterValues());

return Task.CompletedTask;
}

private bool NextParameterValues()
{
foreach (var parameter in _checked)
{
if (parameter.NextVal())
return true;

parameter.ResetValue();
}

return false;
}
}

Code Lab includes this grid-search pattern. The optimizer base owns concurrency, cancellation, strategy cloning, result retention, and iteration execution. Custom code should schedule through the base methods rather than running strategy calculations directly.

Key members include OptimizerParameters, EnqueueParams(), RunIteration(), RunIterationAsync(), WaitForScheduledIterationsAsync(), CombinationCount, and the current cancellation token source.

Combinatorial growth

The default combination count multiplies the selected parameter counts. Narrow ranges first, set realistic increments, and verify cancellation and task-batch behavior before running a large search.

Optimization fitness

A fitness module receives the completed StrategyBase, calculates one score, and assigns Value. Higher values rank ahead of lower values.

using HyperionX.Core.DataCalc;
using HyperionX.Core.DataCalc.Optimization;
using HyperionX.Core.Enums;

namespace HyperionX.Custom.OptimizationFitnesses;

public class ProfitFactorFitness : OptimizationFitness
{
public override void OnCalculatePerformanceValue(StrategyBase strategy)
{
Value = strategy.SystemPerformance.Summary
.GetValue(AnalyticalFeature.ProfitFactor);
}
}

A robust fitness should handle invalid, empty, or non-finite results deliberately. Net profit alone usually rewards unstable or overfit parameter islands. Consider drawdown, trade count, cost sensitivity, and neighboring parameter stability.

Money management

Money management converts price and instrument multiplier inputs into an integer quantity.

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using HyperionX.Core.DataCalc.MoneyManagement;

namespace HyperionX.Custom.MoneyManagements;

public class FixedQuantity : MoneyManagement
{
[Browsable(true)]
[Display(Name = "Quantity", Order = 0)]
public int Quantity { get; set; } = 1;

public override int GetQuantity(double price, double mult)
{
return Quantity;
}
}

The base also exposes StartingCapital and the current SystemPerformance.

In the active release-candidate source, a selected money-management module is evaluated for every entry action, including entries created by managed helpers:

  • Return -1 to preserve the quantity requested by the strategy.
  • Return a positive integer to replace the requested quantity.
  • Return 0 or a negative value other than -1 to suppress the entry.
  • Exit actions are not resized.

The legacy allowMoneyManagement argument remains in the direct SubmitOrder(...) signature but no longer controls that decision in the current source. Because this behavior is Preview and differs from earlier packaged 1.1.10 code, verify the exact release build before distributing a module. Always bound quantity and define behavior for zero, negative, missing, or non-finite price/multiplier inputs.

Commission

A commission module calculates the cost attached to a Trade.

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;
using HyperionX.Core.DataCalc.Commissions;
using HyperionX.Core.Market;

namespace HyperionX.Custom.Commissions;

public class FlatCommission : Commission
{
[Browsable(true)]
[Display(Name = "Commission", Order = 0)]
[DataMember]
public double Amount { get; set; }

public override double GetCommission(Trade trade)
{
return Amount;
}
}

State whether the returned number represents per-side, round-trip, per-unit, or flat-per-trade cost. Keep the result in the currency expected by the research workflow and test partial exits.

Reserved product-default names

The active release-candidate runtime reserves these product-owned display names:

  • Default Optimizer
  • Max Net Profit
  • Strategy control
  • No commission

Name comparison is case-insensitive. A custom optimizer, fitness, money-management, or commission type using the matching name is skipped during discovery and a diagnostic is written to the log. Give every custom module a distinct Name; do not attempt to replace a product default by reusing its label.

Validation matrix

CheckOptimizerFitnessMoney managementCommission
Empty inputNo selected parametersNo trades or missing summaryInvalid price/multiplierNull or incomplete trade state
BoundsCombination count and concurrencyFinite scorePositive maximum quantityNon-negative realistic cost
DeterminismSame inputs schedule same setsSame result yields same scoreSame capital/input yields same sizeSame trade yields same fee
Research realismCancellation and retained-best policyPenalize fragile resultsRespect capital and risk limitsInclude fees before comparing systems

Workflow

  1. Create the extension from its Code Lab template.
  2. Build the full custom project.
  3. Complete desktop runtime activation with Compile Project or a restart.
  4. Open Optimizer or Validator and confirm the new type appears in its selector.
  5. Run a small deterministic test.
  6. Compare the extension against a built-in baseline.
  7. Add realistic commission and slippage assumptions before trusting results.
  8. Review out-of-sample behavior and nearby parameter values.

Continue with Optimization Module Reference, Optimization, and Validation.