Candles
S# supports the following types of candles:
- TimeFrameCandleMessage - a candle based on a time interval, timeframe. You can set both popular intervals (minutes, hours, daily) and customized ones. For example, 21 seconds, 4.5 minutes, etc.
- RangeCandleMessage - a price range candle. A new candle is created when a trade appears with a price that exceeds the acceptable limits. The acceptable limit is formed each time based on the price of the first trade.
- VolumeCandleMessage - a candle is formed until the total volume of trades exceeds a specified limit. If a new trade exceeds the allowable volume, it is included in a new candle.
- TickCandleMessage - the same as VolumeCandleMessage, but the number of trades is used as a limitation instead of volume.
- PnFCandleMessage - a point-and-figure chart candle (X-O chart).
- RenkoCandleMessage - Renko candle.
How to work with candles is shown in the SampleConnection example, which is located in the Samples/Common/SampleConnection folder.
The following images show TimeFrameCandleMessage and RangeCandleMessage charts:
Starting Data Retrieval
- To get candles, create a subscription using the Subscription class:
// Create a subscription to 5-minute candles
var subscription = new Subscription(
DataType.TimeFrame(TimeSpan.FromMinutes(5)), // Data type with timeframe specification
security) // Instrument
{
// Configure additional parameters through the MarketData property
MarketData =
{
// Period for which we request historical data (last 30 days)
From = DateTime.Today.Subtract(TimeSpan.FromDays(30)),
To = DateTime.Now
}
};
- To receive candles, subscribe to the Connector.CandleReceived event, which signals the appearance of a new value for processing:
// Subscribe to the candle reception event
_connector.CandleReceived += OnCandleReceived;
// Candle reception event handler
private void OnCandleReceived(Subscription subscription, ICandleMessage candle)
{
// Here subscription is the subscription object we created
// candle - the received candle
// Check if the candle belongs to our subscription
if (subscription == _candleSubscription)
{
// Draw the candle on the chart
Chart.Draw(_candleElement, candle);
}
}
Tip
The Chart graphical component is used to display candles.
- Next, start the subscription through the Connector.Subscribe method:
// Start the subscription
_connector.Subscribe(subscription);
After this, the Connector.CandleReceived event will begin to be called.
- The Connector.CandleReceived event is called not only when a new candle appears but also when the current one changes.
If you need to display only "complete" candles, you need to check the ICandleMessage.State property of the received candle:
private void OnCandleReceived(Subscription subscription, ICandleMessage candle)
{
// Check if the candle belongs to our subscription
if (subscription != _candleSubscription)
return;
// Check if the candle is completed
if (candle.State == CandleStates.Finished)
{
// Create data for drawing
var chartData = new ChartDrawData();
chartData.Group(candle.OpenTime).Add(_candleElement, candle);
// Draw the candle on the chart
this.GuiAsync(() => Chart.Draw(chartData));
}
}
- Additional parameters can be configured for the subscription:
- Candle building mode - determines whether ready-made data will be requested or built from another data type:
// Request only ready-made data
subscription.MarketData.BuildMode = MarketDataBuildModes.Load;
// Only build from another data type
subscription.MarketData.BuildMode = MarketDataBuildModes.Build;
// Request ready-made data, and if not available - build
subscription.MarketData.BuildMode = MarketDataBuildModes.LoadAndBuild;
- Source for building candles - indicates from which data type to build candles if they are not directly available:
// Building candles from tick trades
subscription.MarketData.BuildFrom = DataType.Ticks;
// Building candles from order books
subscription.MarketData.BuildFrom = DataType.MarketDepth;
// Building candles from Level1
subscription.MarketData.BuildFrom = DataType.Level1;
- Field for building candles - must be specified for certain data types:
// Building candles from the best bid price in Level1
subscription.MarketData.BuildField = Level1Fields.BestBidPrice;
// Building candles from the best ask price in Level1
subscription.MarketData.BuildField = Level1Fields.BestAskPrice;
// Building candles from the middle of the spread in the order book
subscription.MarketData.BuildField = Level1Fields.SpreadMiddle;
- Volume profile - calculation of volume profile for candles:
// Enable volume profile calculation
subscription.MarketData.IsCalcVolumeProfile = true;
Examples of Subscriptions to Different Candle Types
Candles with Standard Timeframe
// 5-minute candles
var timeFrameSubscription = new Subscription(
DataType.TimeFrame(TimeSpan.FromMinutes(5)),
security);
_connector.Subscribe(timeFrameSubscription);
Loading Only Historical Candles
// Loading only historical candles without transitioning to real-time
var historicalSubscription = new Subscription(
DataType.TimeFrame(TimeSpan.FromMinutes(5)),
security)
{
MarketData =
{
From = DateTime.Today.Subtract(TimeSpan.FromDays(30)),
To = DateTime.Today, // Specify end date
BuildMode = MarketDataBuildModes.Load // Only load ready-made data
}
};
_connector.Subscribe(historicalSubscription);
Building Non-Standard Timeframe Candles from Ticks
// Candles with a 21-second timeframe, built from ticks
var customTimeFrameSubscription = new Subscription(
DataType.TimeFrame(TimeSpan.FromSeconds(21)),
security)
{
MarketData =
{
BuildMode = MarketDataBuildModes.Build,
BuildFrom = DataType.Ticks
}
};
_connector.Subscribe(customTimeFrameSubscription);
Building Candles from Order Book Data
// Candles built from the middle of the spread in the order book
var depthBasedSubscription = new Subscription(
DataType.TimeFrame(TimeSpan.FromMinutes(1)),
security)
{
MarketData =
{
BuildMode = MarketDataBuildModes.Build,
BuildFrom = DataType.MarketDepth,
BuildField = Level1Fields.SpreadMiddle
}
};
_connector.Subscribe(depthBasedSubscription);
Candles with Volume Profile
// 5-minute candles with volume profile calculation
var volumeProfileSubscription = new Subscription(
DataType.TimeFrame(TimeSpan.FromMinutes(5)),
security)
{
MarketData =
{
BuildMode = MarketDataBuildModes.LoadAndBuild,
BuildFrom = DataType.Ticks,
IsCalcVolumeProfile = true
}
};
_connector.Subscribe(volumeProfileSubscription);
Volume Candles
// Volume candles (each candle contains 1000 contracts in volume)
var volumeCandleSubscription = new Subscription(
DataType.Volume(1000m), // Specify candle type and volume
security)
{
MarketData =
{
BuildMode = MarketDataBuildModes.Build,
BuildFrom = DataType.Ticks
}
};
_connector.Subscribe(volumeCandleSubscription);
Tick Count Candles
// Tick count candles (each candle contains 1000 trades)
var tickCandleSubscription = new Subscription(
DataType.Tick(1000), // Specify candle type and number of trades
security)
{
MarketData =
{
BuildMode = MarketDataBuildModes.Build,
BuildFrom = DataType.Ticks
}
};
_connector.Subscribe(tickCandleSubscription);
Price Range Candles
// Price range candles with a range of 0.1 units
var rangeCandleSubscription = new Subscription(
DataType.Range(0.1m), // Specify candle type and price range
security)
{
MarketData =
{
BuildMode = MarketDataBuildModes.Build,
BuildFrom = DataType.Ticks
}
};
_connector.Subscribe(rangeCandleSubscription);
Renko Candles
// Renko candles with a step of 0.1
var renkoCandleSubscription = new Subscription(
DataType.Renko(0.1m), // Specify candle type and block size
security)
{
MarketData =
{
BuildMode = MarketDataBuildModes.Build,
BuildFrom = DataType.Ticks
}
};
_connector.Subscribe(renkoCandleSubscription);
Point and Figure Candles (P&F)
// Point and Figure candles
var pnfCandleSubscription = new Subscription(
DataType.PnF(new PnfArg { BoxSize = 0.1m, ReversalAmount = 1 }), // Specify P&F parameters
security)
{
MarketData =
{
BuildMode = MarketDataBuildModes.Build,
BuildFrom = DataType.Ticks
}
};
_connector.Subscribe(pnfCandleSubscription);