Multi-DataSeries Strategy
Demonstrates using indicators attached to different data series. A StrategyFootprintIndicator runs on the primary data series and a StrategyVolumeProfileIndicator runs on a secondary 30-minute series. Prints bar data from both indicators on bar close.
Source: [INSTALL PATH]/API/Samples/MultiDataSeriesStrategy.cs
Class: MultiDataSeriesStrategy : MZpackStrategyBase
What It Covers
- Two indicators on different
DataSeriesIndexvalues AddDataSeries(BarsPeriodType.Minute, 30)for the secondary seriesOnEachTickHandlerwith manual on-bar-close emulation (BarsInProgress == 0 && currentBarIdx > lastBarIdx)- Footprint with full feature set (imbalances, SR zones, absorptions, cluster zones, statistic grid)
- Volume profile with session profiles and developing POC
EnableBacktesting = true
Indicator Setup
Footprint (Primary Data Series)
footprintIndicator = new StrategyFootprintIndicator(this, @"Footprint")
{
DataSeriesIndex = 0, // Primary data series (default)
LeftFootprintStyle = FootprintStyle.Delta,
RightFootprintStyle = FootprintStyle.Volume,
TicksPerLevel = 1,
ShowSessionPOC = true,
ShowSessionVA = true,
SessionDailyProfileMode = SessionDailyProfileMode.Session,
SessionVAIsDeveloping = true,
ShowBarVA = true,
BarVAPercentage = 70,
ShowBarPOC = true,
ShowBarPOCCount = 3,
ShowBarVolume = true,
ShowBarDelta = true,
ShowBarCOT = true,
ShowBarRatioNumbers = true,
ShowImbalance = true,
ImbalancePercentage = 200,
ImbalanceFilter = 20,
ImbalanceMarker = FootprintImbalanceMarker.Always,
ShowImbalanceSRZones = true,
ImbalanceSRZonesConsecutiveLevels = 2,
ImbalanceSRZonesVolumeFilter = 200,
ImbalanceSRZoneEnding = SRZoneEnding.ByBarPOC,
ShowAbsorption = true,
AbsorptionPercentage = 300,
AbsorptionDepth = 2,
AbsorptionFilter = 200,
ShowUnfinishedAuction = true
};
Cluster Zones and Statistic Grid
footprintIndicator.FootprintPresentation[FootprintBaseMVC.RIGHT_FOOTPRINT]
.ClusterZonesShow = true;
footprintIndicator.FootprintPresentation[FootprintBaseMVC.RIGHT_FOOTPRINT]
.ClusterZonesFilterMin = 4000;
footprintIndicator.StatisticGridShow = true;
footprintIndicator.StatisticGridPredictedValuesShow = true;
footprintIndicator.StatisticGridPredictedValuesGaugeShow = true;
Volume Profile (Secondary Data Series)
volumeProfileIndicator = new StrategyVolumeProfileIndicator(this, @"VolumeProfile")
{
DataSeriesIndex = 1, // Secondary data series
Calculate = Calculate.OnBarClose,
ShowProfileType = ProfileType.VP,
ProfileCreation = ProfileCreation.Session,
POCMode = LevelMode.Developing,
VAHVALMode = LevelMode.On,
VWAPMode = VWAPMode.DynamicStdDev1,
ProfileWidthPercentage = 20,
Values1KDivider = false,
StackedProfileCreation1 = ProfileCreation.None,
StackedProfileCreation2 = ProfileCreation.None,
StackedProfileCreation3 = ProfileCreation.None
};
Configuration
In State.Configure, add the secondary data series and set the footprint to on-bar-close:
AddDataSeries(BarsPeriodType.Minute, 30);
footprintIndicator.Calculate = Calculate.OnBarClose;
Data Access
IsFirstTickOfBar does not work correctly in OnMarketData for multi-series strategies. Use BarsInProgress == 0 && currentBarIdx > lastBarIdx to emulate on-bar-close behavior:
protected void StrategyOnEachTickHandler(MarketDataEventArgs e, int currentBarIdx)
{
if (BarsInProgress == 0 && currentBarIdx > lastBarIdx)
{
if (footprintIndicator.FootprintBars.ContainsKey(lastBarIdx))
{
IFootprintBar bar = footprintIndicator.FootprintBars[lastBarIdx];
Print("Footprint (" + footprintIndicator.Instrument.FullName
+ ") bar volume : " + footprintIndicator.FromInternalVolume(bar.Volume));
IVolumeProfile last = volumeProfileIndicator.Profiles.LastOrDefault()
as IVolumeProfile;
if (last != null)
Print("Volume profile (" + volumeProfileIndicator.Instrument.FullName
+ ") total volume : " + volumeProfileIndicator.FromInternalVolume(last.Volume));
}
lastBarIdx = currentBarIdx;
}
}
See Also
- MZpackStrategyBase — base class
- Data Access — mzFootprint — footprint data access
- Data Access — mzVolumeProfile — volume profile data access
- Working with Samples — how to compile samples