Strategy Development
Getting Started
QXFinLib .NET is best suited for the algorithmic trading lifecycle — from concept, modelling, backtesting, optimization, to live trading. The platform is built in C# to provide both low-level control and simplicity.
We will explain step-by-step how to develop your own trading system and test it using historical data.
Create Your First Trading Strategy
A strategy is a set of rules that determines when to buy or sell an instrument.
It can be:
- Backtested on historical data
- Executed in real-time
QXFinLib provides built-in indicators and allows custom indicators.
Building Blocks of a Trading Strategy
Historical Data
- Represented as OHLCV bars
- Can come from CSV, API, or database
- Converted into
TimeDataSeries
Instrument
- Represented by
InstrumentBase - Supports Equity, Futures, Options
Strategy Model
- Custom class inheriting from
StrategyBase - Contains trading logic
Strategy Configuration
StrategyConfigData strategyConfigData = new StrategyConfigData();
strategyConfigData.InitialCapital = 500000;
strategyConfigData.Pyramiding = PyramidingType.Disallow;
strategyConfigData.MaxPyramidingPosition = 1;
strategyConfigData.ContractMultiplier = 1;
strategyConfigData.StopLossTriggerPoint = StopLossTriggerPoint.High_Low_Bar;
strategyConfigData.OrderExecutionAt = OrderExecution.CurrentBar_Close;
StrategyConfigData Properties
| Property | Description |
|---|---|
| InitialCapital | Initial capital |
| FilledOrderCommission | Commission per trade |
| CancelOrderCommission | Cancel cost |
| LimitOrderSlippage | Slippage |
| MarketOrderSlippage | Slippage |
| CommissionType | Per_Contract / Per_Transaction / Percentage |
| StopLossTriggerPoint | Stop loss logic |
| SlippageType | Slippage mode |
| SlippagePercenta | Slippage % |
| OrderExecutionAt | NextBar_Open / CurrentBar_Close |
| Pyramiding | Allow/Disallow |
| MaxPyramidingPosition | Max positions |
| ContractMultiplier | Contract size |
| UserID | User |
| StrategyName | Name |
| PositionSizerType | Position sizing |
| PositionSize | Size |
Required DLL References
using QX.FinLib.Data;
using QX.FinLib.Data.TI;
using QX.FinLib.TS.Strategy;
Strategy Template
using QX.FinLib.Data;
using QX.FinLib.Data.TI;
using QX.FinLib.TS.Strategy;
namespace QX.Strategies
{
[StrategyAttribute("{B9650BDC-74EB-451E-A05E-2BF7056A2BFA}", "EMAStrategy", "EMA Strategy", "QXT")]
public class EMAStrategy : StrategyBase
{
[Parameter("FastLengthPeriod", DefaultValue = 12)]
private int _fastLengthPeriod = 5;
[Parameter("SlowLengthPeriod", DefaultValue = 15)]
private int _slowLengthPeriod = 12;
private IndicatorBase _slowEMAIndicator;
private IndicatorBase _fastEMAIndicator;
protected override void Initialize()
{
_slowEMAIndicator = GetIndicator("EMA");
_fastEMAIndicator = GetIndicator("EMA");
}
protected override void OnStateChanged()
{
if (StrategyState == StrategyState.ActiveMode)
{
_slowEMAIndicator.SetFieldValue("LengthPeriod", _slowLengthPeriod);
_fastEMAIndicator.SetFieldValue("LengthPeriod", _fastLengthPeriod);
}
}
public override void ProcessStrategy()
{
if (CurrentIndex < _slowLengthPeriod)
return;
CrossOver crossover =
_fastEMAIndicator["EMA"].Cross(_slowEMAIndicator["EMA", CurrentIndex]);
if (crossover == CrossOver.Above)
EnterLongAtMarket(1, "Buy");
else if (crossover == CrossOver.Below)
EnterShortAtMarket(1, "Sell");
}
}
}
Strategy Input Parameter
[Parameter("FastLengthPeriod", DefaultValue = 12)]
private int _fastLengthPeriod = 5;
Initialize Method
protected override void Initialize()
{
_slowEMAIndicator = GetIndicator("EMA");
_fastEMAIndicator = GetIndicator("EMA");
}
OnStateChanged Method
protected override void OnStateChanged()
{
if (StrategyState == StrategyState.ActiveMode)
{
_slowEMAIndicator.SetFieldValue("LengthPeriod", _slowLengthPeriod);
_fastEMAIndicator.SetFieldValue("LengthPeriod", _fastLengthPeriod);
}
}
Strategy States
| State | Description |
|---|---|
| ConfigureMode | Initial |
| ActiveMode | Before execution |
| HistoricalMode | Backtesting |
| RealtimeMode | Live |
| TerminateMode | End |
Calculation Mode
OnBarClose
Default mode — runs after bar closes
OnEachTick
Runs on every tick update
protected override void OnStateChanged()
{
if (StrategyState == StrategyState.ConfigureMode)
{
CalculationMode = CalculationMode.OnEachTick;
}
}