### OnInit Method for Indicator Setup Source: https://github.com/quantower/quantowerkb/blob/master/quantower-algo/using-clouds-in-indicator.md In the OnInit method, create two SMA indicators using the built-in Quantower indicator collection and attach them to the HistoricalData. This prepares the indicators for calculation. ```csharp protected override void OnInit() { // create SMA indicators this.fastSma = Core.Instance.Indicators.BuiltIn.SMA(this.FastPeriod, PriceType.Close); this.slowSma = Core.Instance.Indicators.BuiltIn.SMA(this.SlowPeriod, PriceType.Close); // attach them to HistoricalData this.AddIndicator(this.fastSma); this.AddIndicator(this.slowSma); } ``` -------------------------------- ### Full Example: Indicator with Two EMAs Source: https://github.com/quantower/quantowerkb/blob/master/quantower-algo/built-in-indicators.md A complete example demonstrating the creation of two EMA indicators with different periods, adding them to the script, and calculating their difference. This code is intended for use within the Quantower trading platform. ```csharp using System.Drawing; using TradingPlatform.BusinessLayer; namespace IndicatorWithBuiltIn { public class IndicatorWithBuiltIn : Indicator { /// /// Built in indicators /// Indicator fastEMA; Indicator slowEMA; /// /// Indicator's constructor. Contains general information: name, description, LineSeries etc. /// public IndicatorWithBuiltIn() : base() { // Defines indicator's name and description. Name = "IndicatorWithBuiltIn"; // Defines line on demand with particular parameters. AddLineSeries("line1", Color.CadetBlue, 1, LineStyle.Solid); // By default indicator will be applied on main window of the chart SeparateWindow = true; } /// /// This function will be called after creating an indicator as well as after its input params reset or chart (symbol or timeframe) updates. /// protected override void OnInit() { // Create first instance of EMA indicator with Period 12 fastEMA = Core.Indicators.BuiltIn.EMA(12, PriceType.Open); AddIndicator(fastEMA); // Create second instance of EMA indicator with period 26 slowEMA = Core.Indicators.BuiltIn.EMA(26, PriceType.Open); AddIndicator(slowEMA); } /// /// Calculation entry point. This function is called when a price data updates. /// protected override void OnUpdate(UpdateArgs args) { // Calculate difference double difference = fastEMA.GetValue() - slowEMA.GetValue(); ``` -------------------------------- ### Displaying Market Depth Levels on Chart Source: https://github.com/quantower/quantowerkb/blob/master/quantower-algo/indicator-with-custom-painting-gdi.md This example shows how to subscribe to Level 2 quotes and then draw the bid and ask prices on the chart. It requires initializing the subscription in OnInit and then iterating through the market depth data in OnPaintChart. ```csharp protected override void OnInit() { // Subscribe for level 2 quotes this.Symbol.Subscribe(SubscribeQuoteType.Level2); } public override void OnPaintChart(PaintChartEventArgs args) { Graphics gr = args.Graphics; // Create a font Font font = new Font("Arial", 10); // Request current Level2 data var level2Collections = this.Symbol.DepthOfMarket.GetDepthOfMarketAggregatedCollections(); // Draw bids for (int i = 0; i < level2Collections.Bids.Length; i++) gr.DrawString(level2Collections.Bids[i].Price.ToString(), font, Brushes.LightGray, 20, 23 * i + 30); // Draw asks for (int i = 0; i < level2Collections.Asks.Length; i++) gr.DrawString(level2Collections.Asks[i].Price.ToString(), font, Brushes.LightGray, 100, 23 * i + 30); } ``` -------------------------------- ### Quantower Excel RTD Integration Setup Source: https://context7.com/quantower/quantowerkb/llms.txt Steps to enable and set up Quantower's RTD server for live market data in Excel. Ensure Excel and Quantower are the same bitness. ```text Setup: 1. Ensure Excel and Quantower are the same bitness (both 64-bit or both 32-bit) 2. Quantower → General Settings → Excel RTD → enable "Enable Microsoft Excel RTD" 3. Download RTD server: https://updates.quantower.com/misc/RTD/tradingplatform.rtdserver.zip 4. Extract → run register.cmd as Administrator (Excel must be closed) 5. Restart Excel → RTD formulas now work General RTD syntax: =RTD("TradingPlatform";"" ;"Method";"Param1";"Param2";...) ``` -------------------------------- ### Quantower C# Indicator Example Source: https://context7.com/quantower/quantowerkb/llms.txt A C# class implementing a Simple Moving Average indicator for Quantower. It inherits from `Indicator` and uses `OnUpdate` for price callbacks. ```csharp using System.Drawing; using TradingPlatform.BusinessLayer; namespace MyIndicators { public class SimpleMovingAverage : Indicator { [InputParameter("Period", 0, 1, 500, 1, 0)] public int Period = 10; [InputParameter("Price type", 1, variants: new object[] { "Close", PriceType.Close, "Open", PriceType.Open, "High", PriceType.High, "Low", PriceType.Low })] public PriceType priceType = PriceType.Close; public SimpleMovingAverage() : base() { Name = "SimpleMovingAverage"; Description = "Arithmetic mean of N bars"; SeparateWindow = false; AddLineSeries("SMA", Color.DodgerBlue, 2, LineStyle.Solid); } protected override void OnUpdate(UpdateArgs args) { if (Count <= Period) return; double sum = 0.0; for (int i = 0; i < Period; i++) sum += GetPrice(priceType, i); SetValue(sum / Period); // writes to line-series buffer index 0 } } } // Build with F6 → indicator auto-appears in Chart → Indicators lookup ``` -------------------------------- ### Calculating Simple Moving Average (SMA) Source: https://github.com/quantower/quantowerkb/blob/master/quantower-algo/simple-indicator.md Implement the OnUpdate method to perform indicator calculations. This example calculates a 10-period SMA using closing prices, ensuring enough bars are available before calculation. ```csharp /// /// Calculation entry point. This function is called when a price data updates. /// protected override void OnUpdate(UpdateArgs args) { int Period = 10; // Checking, if current amount of bars // more, than period of moving average. If it is true // then the calculation is possible if (Count <= Period) return; double sum = 0.0; // Sum of prices for (int i = 0; i < Period; i++) // Adding bar's price to the sum sum += GetPrice(PriceType.Close, i); // Set value to the "SMA" line buffer. SetValue(sum / Period); ``` -------------------------------- ### Initialize Strategy and Subscribe to Renko Events Source: https://github.com/quantower/quantowerkb/blob/master/quantower-algo/access-to-advanced-aggregations.md Implement the OnRun method to initialize the strategy by downloading historical data with Renko aggregation, creating and attaching SMA indicators, and subscribing to the NewHistoryItem event for processing new bricks. ```csharp protected override void OnRun() { // // check is symbol is null // if (Symbol == null) { Log("Symbol is null", StrategyLoggingLevel.Error); Stop(); return; } try { // // Download history (use Renko aggregation) // renkoHistoricalData = Symbol.GetHistory(new HistoryRequestParameters() { Symbol = Symbol, HistoryType = Symbol.HistoryType, FromTime = Core.Instance.TimeUtils.DateTimeUtcNow.AddHours(-6), ToTime = default, Aggregation = new HistoryAggregationRenko(RenkoPeriod, BrickSize, RenkoStyle) }); // // Subscribe to 'NewHistoryItem' event // renkoHistoricalData.NewHistoryItem += RenkoHistoricalData_NewHistoryItem; // // Create Fast/Slow SMA indicators // fastSmaIndicator = Core.Instance.Indicators.BuiltIn.SMA(FastSmaPeriod, PriceType.Close); slowSmaIndicator = Core.Instance.Indicators.BuiltIn.SMA(SlowSmaPeriod, PriceType.Close); // // Attach our indicators to downloaded HistoricalData // renkoHistoricalData.AddIndicator(fastSmaIndicator); renkoHistoricalData.AddIndicator(slowSmaIndicator); } catch (Exception ex) { Log(ex.Message, StrategyLoggingLevel.Error); Stop(); } } private void RenkoHistoricalData_NewHistoryItem(object sender, HistoryEventArgs e) { // get high price for new brick var highPrice = e.HistoryItem[PriceType.High]; // get low price for new brick var lowPrice = e.HistoryItem[PriceType.Low]; // print message Log($"New brick -- High: {highPrice} | Low: {lowPrice}", StrategyLoggingLevel.Info); } ``` -------------------------------- ### Get Heiken-Ashi Aggregation History Source: https://github.com/quantower/quantowerkb/blob/master/quantower-algo/access-to-advanced-aggregations.md Use HistoryAggregationHeikenAshi to build a Heiken-Ashi chart. Specify the source period and its value. ```csharp var heikenAshiHistoricalData = this.Symbol.GetHistory(new HistoryRequestParameters() { Symbol = this.Symbol, FromTime = DateTime.Now.AddDays(-3), ToTime = DateTime.Now, HistoryType = this.Symbol.HistoryType, Aggregation = new HistoryAggregationHeikenAshi(HeikenAshiSource.Minute, 1), }); ``` -------------------------------- ### Get Time Aggregation History Source: https://github.com/quantower/quantowerkb/blob/master/quantower-algo/access-to-advanced-aggregations.md Use HistoryAggregationTime to build a Time chart. Specify the desired time period for aggregation. ```csharp var timeBarHistoricalData = this.Symbol.GetHistory(new HistoryRequestParameters() { Symbol = this.Symbol, FromTime = DateTime.Now.AddDays(-3), ToTime = DateTime.Now, HistoryType = this.Symbol.HistoryType, Period = Period.MIN15, Aggregation = new HistoryAggregationTime(Period.MIN15), }); ``` -------------------------------- ### BeginCloud Method Signature Source: https://github.com/quantower/quantowerkb/blob/master/quantower-algo/using-clouds-in-indicator.md This method marks the beginning of a cloud area between two line series. Specify the indices of the two lines, the desired color, and an optional offset. ```csharp /// /// Marks cloud begin between two line series with specific color /// /// First line series index /// Second line series index /// Cloud color /// Offset protected void BeginCloud(int line1Index, int line2Index, Color color, int offset = 0) ``` -------------------------------- ### Get Tick Aggregation History Source: https://github.com/quantower/quantowerkb/blob/master/quantower-algo/access-to-advanced-aggregations.md Use HistoryAggregationTick to build a simple Tick chart. Specify the number of ticks for aggregation. ```csharp var tickhistoricalData = this.Symbol.GetHistory(new HistoryRequestParameters() { Symbol = this.Symbol, FromTime = DateTime.Now.AddHours(-3), ToTime = DateTime.Now, HistoryType = this.Symbol.VolumeType == SymbolVolumeType.Volume ? HistoryType.Last : HistoryType.BidAsk, Period = Period.TICK1, Aggregation = new HistoryAggregationTick(1), }); ``` -------------------------------- ### Initialize Indicator with Historical Data and SMA Source: https://github.com/quantower/quantowerkb/blob/master/quantower-algo/downloading-history.md In the `OnInit` method, download historical data for the main symbol across different timeframes and apply the SMA indicator. This sets up the initial calculations for the indicator. ```csharp protected override void OnInit() { // Download history for current symbol for different timeframes and apply SMA indicator // 5 min IHistoricalData data5MinCurrent = this.Symbol.GetHistory(Period.MIN5, HistoryType.Bid, DateTime.UtcNow.AddDays(-1)); data5MinCurrent.AddIndicator(sma5MinCurrent = Core.Indicators.BuiltIn.SMA(10, PriceType.Close)); // 15 min IHistoricalData data15MinCurrent = this.Symbol.GetHistory(Period.MIN15, HistoryType.Bid, DateTime.UtcNow.AddDays(-1)); data15MinCurrent.AddIndicator(sma15MinMainCurrent = Core.Indicators.BuiltIn.SMA(10, PriceType.Close)); // 30 min IHistoricalData data30MinCurrent = this.Symbol.GetHistory(Period.MIN30, HistoryType.Bid, DateTime.UtcNow.AddDays(-1)); data30MinCurrent.AddIndicator(sma30MinMainCurrent = Core.Indicators.BuiltIn.SMA(10, PriceType.Close)); // Download history for additional symbol (if specified) for different timeframes and apply SMA indicator if (AdditionalSymbol != null) { // 5 min ``` -------------------------------- ### Kagi Aggregation Example Source: https://github.com/quantower/quantowerkb/blob/master/quantower-algo/access-to-advanced-aggregations.md Retrieves historical data using Kagi aggregation. Requires specifying the base period and the reversal value. ```csharp new HistoryAggregationKagi(Period period, int reversal); ``` ```csharp var kagiHistoricalData = this.Symbol.GetHistory(new HistoryRequestParameters() { Symbol = this.Symbol, FromTime = DateTime.Now.AddDays(-1), ToTime = DateTime.Now, HistoryType = this.Symbol.HistoryType, Aggregation = new HistoryAggregationKagi(Period.MIN15, 10), }); ``` -------------------------------- ### Place Market, Limit, and Stop Orders in C# Source: https://context7.com/quantower/quantowerkb/llms.txt Demonstrates the shortest forms for placing market, limit, and stop orders using Core.Instance.PlaceOrder. Ensure the symbol, account, and side are correctly specified. ```csharp // --- Place Market order (shortest form) --- Core.Instance.PlaceOrder(this.symbol, this.account, Side.Buy); ``` ```csharp // --- Place Limit order --- Core.Instance.PlaceOrder(this.symbol, this.account, Side.Buy, price: this.symbol.Bid - this.symbol.TickSize * 5); ``` ```csharp // --- Place Stop order --- Core.Instance.PlaceOrder(this.symbol, this.account, Side.Sell, triggerPrice: this.symbol.Ask + 5 * this.symbol.TickSize); ``` -------------------------------- ### Get Range Bars Aggregation History Source: https://github.com/quantower/quantowerkb/blob/master/quantower-algo/access-to-advanced-aggregations.md Use HistoryAggregationRangeBars to build a Range Bars chart. Specify the height of each bar in ticks. ```csharp var rangeBarHistoricalData = this.Symbol.GetHistory(new HistoryRequestParameters() { Symbol = this.Symbol, FromTime = DateTime.Now.AddHours(-3), ToTime = DateTime.Now, HistoryType = this.Symbol.HistoryType, Aggregation = new HistoryAggregationRangeBars(10), }); ``` -------------------------------- ### Get Account Balance Source: https://github.com/quantower/quantowerkb/blob/master/quantower-algo/access-to-crypto-account-and-balances.md Logs the currency name and balance of a selected account. Ensure the input account is not null before accessing its properties. ```csharp public class TestStrategy : Strategy { [InputParameter("Selected account", 10)] public Account inputAccount; protected override void OnRun() { if (inputAccount != null) { Log("Currency name: " + inputAccount.AccountCurrency); Log("Balance: " + inputAccount.Balance); } } } ``` -------------------------------- ### Place Full Order with SL/TP in C# Source: https://context7.com/quantower/quantowerkb/llms.txt Shows how to place a limit order with Stop Loss and Take Profit levels using the full form of PlaceOrderRequestParameters. Check the result status for failure messages. ```csharp // --- Full form with SL/TP bracket --- var result = Core.Instance.PlaceOrder(new PlaceOrderRequestParameters { Account = this.account, Symbol = this.symbol, Side = Side.Buy, OrderTypeId = OrderType.Limit, Price = this.symbol.Bid - this.symbol.TickSize * 10, Quantity = 2, TimeInForce = TimeInForce.Day, StopLoss = SlTpHolder.CreateSL(20, PriceMeasurement.Offset), TakeProfit = SlTpHolder.CreateSL(10, PriceMeasurement.Offset), }); if (result.Status == TradingOperationResultStatus.Failure) Log($"Order failed: {result.Message}", StrategyLoggingLevel.Error); ``` -------------------------------- ### Volume Bars Aggregation Example Source: https://github.com/quantower/quantowerkb/blob/master/quantower-algo/access-to-advanced-aggregations.md Retrieves historical data using Volume Bars aggregation. Requires specifying the base volume value. ```csharp new HistoryAggregationVolume(int volumeValue); ``` ```csharp var volumeBarsHistoricalData = this.Symbol.GetHistory(new HistoryRequestParameters() { Symbol = this.Symbol, FromTime = DateTime.Now.AddHours(-4), ToTime = DateTime.Now, Period = Period.TICK1, HistoryType = this.Symbol.HistoryType, Aggregation = new HistoryAggregationVolume(1000), }); ``` -------------------------------- ### Create a Quantower Trading Strategy Source: https://context7.com/quantower/quantowerkb/llms.txt Inherit from the Strategy class and implement lifecycle callbacks like OnRun and OnStop. Subscribe to symbol events like NewQuote and NewLast. Use Core.Instance for order execution. ```csharp using System.Collections.Generic; using TradingPlatform.BusinessLayer; namespace MyStrategies { public class QuoteCounterStrategy : Strategy { [InputParameter("Symbol")] public Symbol symbol; [InputParameter("Account")] public Account account; int quotesCount = 0; int lastCount = 0; protected override void OnRun() { if (symbol == null || account == null) { Log("Symbol or Account not set", StrategyLoggingLevel.Error); return; } symbol.NewQuote += OnNewQuote; symbol.NewLast += OnNewLast; Log("Strategy started", StrategyLoggingLevel.Info); } protected override void OnStop() { symbol.NewQuote -= OnNewQuote; symbol.NewLast -= OnNewLast; Log("Strategy stopped", StrategyLoggingLevel.Trading); } private void OnNewQuote(Symbol s, Quote q) => quotesCount++; private void OnNewLast(Symbol s, Last l) { lastCount++; Log($"Last: {l.Price} × {l.Size}", StrategyLoggingLevel.Trading); } protected override List OnGetMetrics() { var m = base.OnGetMetrics(); m.Add(new StrategyMetric { Name = "Quotes", FormattedValue = quotesCount.ToString() }); m.Add(new StrategyMetric { Name = "Lasts", FormattedValue = lastCount.ToString() }); return m; } } } // Build → visible in Strategies Manager → set Symbol + Account → Run ``` -------------------------------- ### Line Break Aggregation Example Source: https://github.com/quantower/quantowerkb/blob/master/quantower-algo/access-to-advanced-aggregations.md Fetches historical data with Line Break aggregation. Requires setting the base period and the line break value. ```csharp new HistoryAggregationLineBreak(Period period, int lineBreak); ``` ```csharp var lineBreakHistoricalData = this.Symbol.GetHistory(new HistoryRequestParameters() { Symbol = this.Symbol, FromTime = DateTime.Now.AddDays(-1), ToTime = DateTime.Now, HistoryType = this.Symbol.HistoryType, Aggregation = new HistoryAggregationLineBreak(Period.MIN15, 3), }); ``` -------------------------------- ### Place Basic Order (Buy/Sell) Source: https://github.com/quantower/quantowerkb/blob/master/quantower-algo/trading-operations.md This is the shortest form to place a 1 lot position for a specified symbol and account. It defaults to a Market order type. ```csharp Core.Instance.PlaceOrder(this.symbol, this.account, Side.Buy); ``` -------------------------------- ### Renko Aggregation Example Source: https://github.com/quantower/quantowerkb/blob/master/quantower-algo/access-to-advanced-aggregations.md Retrieves historical data using Renko aggregation. Requires specifying the base period, brick size, and Renko style. ```csharp new HistoryAggregationRenko(Period period, int brickSize, RenkoStyle renkoStyle, int extension = 100, int inversion = 100, bool showWicks = false, bool buildCurrentBar = true) ``` ```csharp var renkoHistoricalData = this.Symbol.GetHistory(new HistoryRequestParameters() { Symbol = this.Symbol, FromTime = DateTime.Now.AddDays(-1), ToTime = DateTime.Now, HistoryType = this.Symbol.HistoryType, Aggregation = new HistoryAggregationRenko(Period.MIN1, 10, RenkoStyle.AdvancedClassic, 100, 100, true, true), }); ``` -------------------------------- ### Initialize Indicator Logic Source: https://github.com/quantower/quantowerkb/blob/master/quantower-algo/simple-moving-average-example.md The OnInit function is intentionally left empty as this indicator does not require any specific one-time initialization logic when added to a chart. ```csharp protected override void OnInit() { } ``` -------------------------------- ### Modify Order Price Source: https://github.com/quantower/quantowerkb/blob/master/quantower-algo/trading-operations.md Adjust the price of an order by passing the new price value to the ModifyOrder function. The example shows setting the price relative to the current bid. ```csharp Core.Instance.ModifyOrder(orderToModify, price: this.symbol.Bid - 10 * this.symbol.TickSize); ```