├── README.md └── Indicators ├── IndicatorFundingRates.cs ├── IndicatorTrueRange.cs ├── IndicatorSUM.cs ├── IndicatorAbnormalVolume.cs ├── IndicatorOpenInterest.cs ├── IndicatorBalanceOfPower.cs ├── IndicatorRateOfChange.cs ├── IndicatorRLarryWilliams.cs ├── IndicatorCamarilla.cs ├── IndicatorPivotPointMovingAverage.cs ├── IndicatorMomentum.cs ├── IndicatorRelativeVigorIndex.cs ├── IndicatorSimpleMovingAverage.cs ├── IndicatorFYL.cs ├── IndicatorAroon.cs ├── IndicatorAwesomeOscillator.cs ├── IndicatorKairiRelativeIndex.cs ├── IndicatorLinearlyWeightedMovingAverage.cs ├── IndicatorHullMovingAverage.cs ├── IndicatorChandeMomentumOscillator.cs ├── IndicatorBandas.cs ├── IndicatorBBS.cs ├── IndicatorPolynomialRegressionChannel.cs ├── IndicatorPositiveVolumeIndex.cs ├── IndicatorModifiedMovingAverage.cs ├── IndicatorMoneyFlowIndex.cs ├── IndicatorDeltaDivergenceReversal.cs ├── IndicatorSuperTrend.cs ├── IndicatorRegressionLine.cs ├── IndicatorTripleExponentialAverage.cs ├── IndicatorPriceChannel.cs ├── IndicatorStochasticRelativeStrengthIndex.cs ├── IndicatorTimeHistogram.cs ├── IndicatorAverageTrueRange.cs ├── IndicatorContador.cs ├── IndicatorMcGinleyDynamic.cs ├── IndicatorStandardDeviation.cs ├── IndicatorAccelerationOscillator.cs ├── IndicatorRelativeStrengthIndexSmoothed.cs ├── IndicatorPriceOscillator.cs ├── IndicatorSchaffTrendCycle.cs ├── IndicatorBollingerBands.cs ├── IndicatorMovingAverageEnvelope.cs ├── IndicatorSmoothedMovingAverage.cs ├── IndicatorMovingAverageOfOscillator.cs ├── IndicatorQstick.cs ├── IndicatorBollingerBandsFlat.cs ├── IndicatorCommodityChannelIndex.cs ├── IndicatorKeltnerChannel.cs ├── Indicator3MASignal.cs ├── IndicatorPercentagePriceOscillator.cs ├── IndicatorExponentialMovingAverage.cs ├── IndicatorATRTrailingStopWithFibRetracements.cs ├── IndicatorIchimoku.cs ├── IndicatorDeltaFlow.cs ├── IndicatorSeparatedAverageTrueRange.cs ├── IndicatorTrueStrengthIndex.cs └── IndicatorRoundNumbers.cs /README.md: -------------------------------------------------------------------------------- 1 | # Scripts 2 | -------------------------------------------------------------------------------- /Indicators/IndicatorFundingRates.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2021. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace BarsDataIndicators; 7 | 8 | public sealed class IndicatorFundingRates : Indicator 9 | { 10 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorFundingRates.cs"; 11 | 12 | public IndicatorFundingRates() 13 | { 14 | this.Name = "Funding Rates"; 15 | this.Description = ""; 16 | 17 | this.AddLineSeries("FundingRate", Color.Green, 2); 18 | this.SeparateWindow = true; 19 | } 20 | 21 | protected override void OnUpdate(UpdateArgs args) 22 | { 23 | double fundingRate = this.FundingRate(); 24 | 25 | if (!double.IsNaN(fundingRate)) 26 | fundingRate *= 100; 27 | 28 | this.SetValue(fundingRate); 29 | } 30 | } -------------------------------------------------------------------------------- /Indicators/IndicatorTrueRange.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System; 4 | using System.Drawing; 5 | using TradingPlatform.BusinessLayer; 6 | 7 | namespace VolatilityIndicators; 8 | 9 | public class IndicatorTrueRange : Indicator 10 | { 11 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorTrueRange.cs"; 12 | 13 | public IndicatorTrueRange() 14 | : base() 15 | { 16 | // Defines indicator's name and description. 17 | Name = "True Range"; 18 | 19 | // Defines line on demand with particular parameters. 20 | this.AddLineSeries("TR", Color.CadetBlue, 1, LineStyle.Solid); 21 | 22 | this.SeparateWindow = true; 23 | } 24 | 25 | protected override void OnUpdate(UpdateArgs args) 26 | { 27 | double tr = this.CalculateTrueRange(); 28 | 29 | this.SetValue(tr); 30 | } 31 | 32 | public double CalculateTrueRange(int offset = 0) 33 | { 34 | double hi = this.GetPrice(PriceType.High, offset); 35 | double lo = this.GetPrice(PriceType.Low, offset); 36 | 37 | double prevClose = (Count <= offset + 1) ? this.Close(offset) 38 | : this.Close(offset + 1); 39 | 40 | return Math.Max(hi - lo, Math.Max(Math.Abs(prevClose - hi), Math.Abs(prevClose - lo))); 41 | } 42 | } -------------------------------------------------------------------------------- /Indicators/IndicatorSUM.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2023. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace OscillatorsIndicators; 7 | 8 | public class IndicatorSUM : Indicator 9 | { 10 | #region Parameters 11 | [InputParameter("Period", 10, 1, 99999, 0, 0)] 12 | public int Period = 14; 13 | 14 | [InputParameter("Sources prices", 1, variants: new object[] { 15 | "Close", PriceType.Close, 16 | "Open", PriceType.Open, 17 | "High", PriceType.High, 18 | "Low", PriceType.Low, 19 | "Typical", PriceType.Typical, 20 | "Medium", PriceType.Median, 21 | "Weighted", PriceType.Weighted, 22 | "Volume", PriceType.Volume, 23 | "Open interest", PriceType.OpenInterest 24 | })] 25 | public PriceType SourcePrice = PriceType.Close; 26 | 27 | public override string ShortName => $"{this.Name} ({this.Period}: {this.SourcePrice})"; 28 | 29 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorSUM.cs"; 30 | 31 | #endregion Parameters 32 | 33 | public IndicatorSUM() 34 | { 35 | this.Name = "Sum"; 36 | this.AddLineSeries("Sum", Color.Orange, 1, LineStyle.Solid); 37 | this.SeparateWindow = true; 38 | } 39 | 40 | protected override void OnUpdate(UpdateArgs args) 41 | { 42 | var prevValue = this.Count > 1 ? this.GetValue(1) : 0; 43 | var prevPrice = this.Count <= this.Period ? 0 : this.GetPrice(this.SourcePrice, this.Period); 44 | 45 | var value = this.GetPrice(this.SourcePrice) + (double.IsNaN(prevValue) ? 0 : prevValue) - prevPrice; 46 | 47 | this.SetValue(value); 48 | } 49 | } -------------------------------------------------------------------------------- /Indicators/IndicatorAbnormalVolume.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace VolumeIndicators; 7 | 8 | public class IndicatorAbnormalVolume : Indicator, IWatchlistIndicator 9 | { 10 | [InputParameter] 11 | public int Period = 60; 12 | 13 | [InputParameter] 14 | public double SignalLine = 5.0; 15 | 16 | [InputParameter] 17 | public Color MarkerColor = Color.Green; 18 | 19 | public int MinHistoryDepths => Period; 20 | public override string ShortName => "AV"; 21 | 22 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorAbnormalVolume.cs"; 23 | 24 | public IndicatorAbnormalVolume() 25 | : base() 26 | { 27 | this.Name = "Abnormal Volume"; 28 | this.Description = "Shows the ratio of the volume of the current bar to the 'Period' of the previous ones"; 29 | 30 | this.AddLineSeries("Main Line", Color.CadetBlue, 1, LineStyle.Histogramm); 31 | this.AddLineSeries("Signal Line", Color.CadetBlue, 1, LineStyle.Solid); 32 | this.SeparateWindow = true; 33 | } 34 | 35 | protected override void OnInit() 36 | { 37 | // Add your initialization code here 38 | } 39 | 40 | protected override void OnUpdate(UpdateArgs args) 41 | { 42 | if (this.Count <= this.Period) 43 | return; 44 | 45 | double sum = 0.0; // Sum of prices 46 | for (int i = 1; i <= this.Period; i++) 47 | sum += this.Volume(i); 48 | 49 | double averageVolume = sum / this.Period; 50 | double value = this.Volume() / averageVolume; 51 | this.SetValue(value); 52 | this.SetValue(this.SignalLine, 1); 53 | LinesSeries[0].RemoveMarker(0); 54 | if (GetValue() >= GetValue(0, 1)) 55 | { 56 | LinesSeries[0].SetMarker(0, new IndicatorLineMarker(MarkerColor, IndicatorLineMarkerIconType.DownArrow)); 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /Indicators/IndicatorOpenInterest.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace BarsDataIndicators; 7 | 8 | public sealed class IndicatorOpenInterest : Indicator, IWatchlistIndicator 9 | { 10 | [InputParameter("Smooth period", 10, 1, int.MaxValue, 1, 0)] 11 | public int MaPeriod; 12 | 13 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorOpenInterest.cs"; 14 | 15 | public override string ShortName 16 | { 17 | get 18 | { 19 | string name = this.Name; 20 | if (this.LinesSeries[1].Visible) 21 | name += $" ({this.MaPeriod})"; 22 | 23 | return name; 24 | } 25 | } 26 | 27 | public int MinHistoryDepths => this.MaPeriod; 28 | 29 | private Indicator sma; 30 | 31 | public IndicatorOpenInterest() 32 | : base() 33 | { 34 | // Defines indicator's group, name and description. 35 | this.Name = "Open Interest"; 36 | this.Description = "The total number of outstanding derivative contracts"; 37 | 38 | this.MaPeriod = 10; 39 | this.SeparateWindow = true; 40 | 41 | // Defines line on demand with particular parameters. 42 | this.AddLineSeries("OpenInterest", Color.Green, 2, LineStyle.Solid); 43 | this.AddLineSeries("Smooth OI", Color.Orange, 2, LineStyle.Solid); 44 | } 45 | 46 | protected override void OnInit() 47 | { 48 | this.sma = Core.Indicators.BuiltIn.SMA(this.MaPeriod, PriceType.OpenInterest); 49 | this.AddIndicator(this.sma); 50 | } 51 | 52 | protected override void OnUpdate(UpdateArgs args) 53 | { 54 | base.OnUpdate(args); 55 | 56 | if (this.Count > 0 && this.HistoricalData.Count >= this.Count) 57 | { 58 | double openInterest = this.OpenInterest(); 59 | this.SetValue(openInterest); 60 | 61 | if (this.Count > this.MaPeriod) 62 | this.SetValue(this.sma.GetValue(), 1, 0); 63 | } 64 | } 65 | 66 | protected override void OnClear() 67 | { 68 | if (this.sma != null) 69 | { 70 | this.RemoveIndicator(this.sma); 71 | this.sma?.Dispose(); 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /Indicators/IndicatorBalanceOfPower.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace OscillatorsIndicators; 7 | 8 | public class IndicatorBalanceOfPower : Indicator 9 | { 10 | private const int CURRENT_BAR_OFFSET = 0; 11 | private const PriceType INDICATOR_SOURCE_PRICE_TYPE = PriceType.Close; 12 | 13 | [InputParameter("Smoothing period", 0, 1, 999, 1, 2)] 14 | public int SmoothingPeriod = 5; 15 | 16 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorBalanceOfPower.cs"; 17 | 18 | [InputParameter("Smoothing Type", 3, variants: new object[] 19 | { 20 | "Simple Moving Average", MaMode.SMA, 21 | "Exponential Moving Average", MaMode.EMA, 22 | "Smoothed Moving Average", MaMode.SMMA, 23 | "Linearly Weighted Moving Average", MaMode.LWMA, 24 | })] 25 | public MaMode MaType = MaMode.SMA; 26 | 27 | public override string ShortName => $"BOP ({this.SmoothingPeriod})"; 28 | 29 | private HistoricalDataCustom smoothingSource; 30 | private Indicator smoothing; 31 | 32 | public IndicatorBalanceOfPower() 33 | : base() 34 | { 35 | this.Name = "Balance Of Power"; 36 | this.AddLineSeries("BoP Line", Color.CadetBlue, 1, LineStyle.Solid); 37 | this.AddLineSeries("Smoothed Line", Color.Blue, 1, LineStyle.Solid); 38 | this.SeparateWindow = true; 39 | } 40 | protected override void OnInit() 41 | { 42 | this.smoothing = Core.Instance.Indicators.BuiltIn.MA(this.SmoothingPeriod, INDICATOR_SOURCE_PRICE_TYPE, this.MaType); 43 | this.smoothingSource = new HistoricalDataCustom(this); 44 | this.smoothingSource.AddIndicator(this.smoothing); 45 | } 46 | protected override void OnUpdate(UpdateArgs args) 47 | { 48 | if (this.Count <= this.SmoothingPeriod + 1) 49 | return; 50 | 51 | var highLowDeltaPrice = this.High(CURRENT_BAR_OFFSET) - this.Low(CURRENT_BAR_OFFSET); 52 | var bop = highLowDeltaPrice != default 53 | ? (this.Close(CURRENT_BAR_OFFSET) - this.Open(CURRENT_BAR_OFFSET)) / highLowDeltaPrice 54 | : default; 55 | 56 | this.smoothingSource[INDICATOR_SOURCE_PRICE_TYPE] = bop; 57 | 58 | this.SetValue(bop); 59 | this.SetValue(this.smoothing.GetValue(), 1); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Indicators/IndicatorRateOfChange.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace Oscillators; 7 | 8 | public sealed class IndicatorRateOfChange : Indicator, IWatchlistIndicator 9 | { 10 | // Displays 'Period' input parameter as input field. 11 | [InputParameter("Period of momentum", 0, 1, 999, 1, 0)] 12 | public int Period = 9; 13 | 14 | public int MinHistoryDepths => this.Period + 1; 15 | public override string ShortName => $"ROC ({this.Period})"; 16 | public override string HelpLink => "https://help.quantower.com/analytics-panels/chart/technical-indicators/oscillators/rate-of-change"; 17 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorRateOfChange.cs"; 18 | 19 | /// 20 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 21 | /// 22 | public IndicatorRateOfChange() 23 | : base() 24 | { 25 | // Defines indicator's name and description. 26 | this.Name = "Rate of Change"; 27 | this.Description = "Shows the speed at which price is changing"; 28 | 29 | // Defines line on demand with particular parameters. 30 | this.AddLineSeries("ROC", Color.Brown, 2, LineStyle.Solid); 31 | this.AddLineLevel(0d, "Zero", Color.Gray, 2, LineStyle.Solid); 32 | 33 | this.SeparateWindow = true; 34 | } 35 | 36 | /// 37 | /// Calculation entry point. This function is called when a price data updates. 38 | /// Will be runing under the HistoricalBar mode during history loading. 39 | /// Under NewTick during realtime. 40 | /// Under NewBar if start of the new bar is required. 41 | /// 42 | /// Provides data of updating reason and incoming price. 43 | protected override void OnUpdate(UpdateArgs args) 44 | { 45 | // Skip some period for correct calculation. 46 | if (this.Count < this.MinHistoryDepths) 47 | return; 48 | 49 | // Get close price. 50 | double price = this.Close(); 51 | 52 | // Get close price by offset. 53 | double priceN = this.Close(this.Period); 54 | 55 | double roc = 100 * (price - priceN) / priceN; 56 | 57 | // Set value to 'ROC' line buffer. 58 | this.SetValue(roc); 59 | } 60 | } -------------------------------------------------------------------------------- /Indicators/IndicatorRLarryWilliams.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Drawing; 6 | using System.Linq; 7 | using TradingPlatform.BusinessLayer; 8 | 9 | namespace Oscillators; 10 | 11 | public sealed class IndicatorRLarryWilliams : Indicator, IWatchlistIndicator 12 | { 13 | // Displays Input Parameter as input field (or checkbox if value type is bolean). 14 | [InputParameter("Period", 0, 1, 9999, 1, 0)] 15 | public int Period = 14; 16 | 17 | public int MinHistoryDepths => this.Period; 18 | public override string ShortName => $"RLW ({this.Period})"; 19 | public override string HelpLink => "https://help.quantower.com/analytics-panels/chart/technical-indicators/oscillators/r-larry-williams"; 20 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorQstick.cs"; 21 | 22 | /// 23 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 24 | /// 25 | public IndicatorRLarryWilliams() 26 | : base() 27 | { 28 | // Serves for an identification of related indicators with different parameters. 29 | this.Name = "%R Larry Williams"; 30 | this.Description = "Uses Stochastic to determine overbought and oversold levels"; 31 | 32 | // Defines line on demand with particular parameters. 33 | this.AddLineSeries("RLW Line", Color.Blue, 1, LineStyle.Solid); 34 | this.AddLineLevel(-20, "Upper Limit", Color.Red, 1, LineStyle.Solid); 35 | this.AddLineLevel(-80, "Lower Limit", Color.Red, 1, LineStyle.Solid); 36 | 37 | this.SeparateWindow = true; 38 | } 39 | 40 | /// 41 | /// Calculation entry point. This function is called when a price data updates. 42 | /// Will be runing under the HistoricalBar mode during history loading. 43 | /// Under NewTick during realtime. 44 | /// Under NewBar if start of the new bar is required. 45 | /// 46 | /// Provides data of updating reason and incoming price. 47 | protected override void OnUpdate(UpdateArgs args) 48 | { 49 | if (this.Count < this.Period) 50 | return; 51 | 52 | double highestPrice = Enumerable.Range(0, this.Period).Select(i => this.GetPrice(PriceType.High, i)).Max(); 53 | double lowestPrice = Enumerable.Range(0, this.Period).Select(i => this.GetPrice(PriceType.Low, i)).Min(); 54 | 55 | if (highestPrice - lowestPrice > 1e-7) 56 | this.SetValue(-100 * (highestPrice - this.GetPrice(PriceType.Close)) / (highestPrice - lowestPrice)); 57 | } 58 | } -------------------------------------------------------------------------------- /Indicators/IndicatorCamarilla.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System; 4 | using System.Drawing; 5 | using TradingPlatform.BusinessLayer; 6 | 7 | namespace TrendIndicators; 8 | 9 | public class IndicatorCamarilla : Indicator 10 | { 11 | private HistoricalData dailyHistoricalData; 12 | 13 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorCamarilla.cs"; 14 | 15 | public IndicatorCamarilla() 16 | : base() 17 | { 18 | Name = "Camarilla"; 19 | 20 | AddLineSeries("R1", Color.IndianRed, 1, LineStyle.Solid); 21 | AddLineSeries("S1", Color.IndianRed, 1, LineStyle.Solid); 22 | 23 | AddLineSeries("R2", Color.OrangeRed, 1, LineStyle.Solid); 24 | AddLineSeries("S2", Color.OrangeRed, 1, LineStyle.Solid); 25 | 26 | AddLineSeries("R3", Color.DarkOliveGreen, 1, LineStyle.Solid); 27 | AddLineSeries("S3", Color.DarkOliveGreen, 1, LineStyle.Solid); 28 | 29 | AddLineSeries("R4", Color.Green, 1, LineStyle.Solid); 30 | AddLineSeries("S4", Color.Green, 1, LineStyle.Solid); 31 | 32 | SeparateWindow = false; 33 | } 34 | 35 | protected override void OnInit() 36 | { 37 | // Download daily historical data with a ten-day margin 38 | this.dailyHistoricalData = this.Symbol.GetHistory(Period.DAY1, Time(Count - 1).Date.AddDays(-10)); 39 | } 40 | 41 | protected override void OnUpdate(UpdateArgs args) 42 | { 43 | int index = (int)dailyHistoricalData.GetIndexByTime(Time().Date.AddDays(-1).Ticks, SeekOriginHistory.End); 44 | 45 | // Get the bar value of the previous day 46 | HistoryItemBar previousDayBar = (HistoryItemBar)dailyHistoricalData[index]; 47 | 48 | for (int i = 1; i <= 8; i++) 49 | { 50 | int number = (int)Math.Round((double)i / 2, MidpointRounding.AwayFromZero); 51 | if (i % 2 == 1) 52 | SetValue((previousDayBar.High - previousDayBar.Low) * (1.1 / Fibonacci(4 - number + 1)) + previousDayBar.Close, i - 1); //Set value for resistance 53 | else 54 | SetValue(previousDayBar.Close - (previousDayBar.High - previousDayBar.Low) * (1.1 / Fibonacci(4 - number + 1)), i - 1);//Set value to support 55 | } 56 | } 57 | 58 | private int Fibonacci(int n) //Get coefficient - 2,4,6,12 in this case 59 | { 60 | int a = 2; 61 | int b = 0; 62 | if (n == 1) 63 | return a; 64 | for (int i = 2; i <= n; i++) 65 | { 66 | if (i % 2 == 0) 67 | b = a * 2; 68 | else 69 | b = a * 3 / 2; 70 | a = b; 71 | } 72 | return b; 73 | } 74 | } -------------------------------------------------------------------------------- /Indicators/IndicatorPivotPointMovingAverage.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace MovingAverages; 7 | 8 | public sealed class IndicatorPivotPointMovingAverage : Indicator, IWatchlistIndicator 9 | { 10 | // Define 'Period' input parameter and set allowable range (from 1 to 999) 11 | [InputParameter("Period of PPMA", 0, 1, 9999, 1, 0)] 12 | public int Period = 5; 13 | 14 | public int MinHistoryDepths => this.Period; 15 | public override string ShortName => $"PPMA ({this.Period})"; 16 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorPivotPointMovingAverage.cs"; 17 | 18 | /// 19 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 20 | /// 21 | public IndicatorPivotPointMovingAverage() 22 | { 23 | // Defines indicator's name and description. 24 | this.Name = "Pivot Point Moving Average"; 25 | this.Description = "Uses the pivot point calculation as the input a simple moving average"; 26 | 27 | // Define two lines with particular parameters 28 | this.AddLineSeries("PP", Color.CadetBlue, 1, LineStyle.Solid); 29 | this.AddLineSeries("PPMA", Color.Yellow, 1, LineStyle.Solid); 30 | 31 | this.SeparateWindow = false; 32 | } 33 | 34 | /// 35 | /// Calculation entry point. This function is called when a price data updates. 36 | /// Will be runing under the HistoricalBar mode during history loading. 37 | /// Under NewTick during realtime. 38 | /// Under NewBar if start of the new bar is required. 39 | /// 40 | /// Provides data of updating reason and incoming price. 41 | protected override void OnUpdate(UpdateArgs args) 42 | { 43 | // Get pivot value for current bar 44 | double pivot = this.GetPivotByOffset(0); 45 | 46 | // Set "pivot" value to the 'PP' line buffer (line index is 0) 47 | this.SetValue(pivot); 48 | 49 | // Skip some period for correct calculation. 50 | if (this.Count < this.MinHistoryDepths) 51 | return; 52 | 53 | // Calculate the sum of pivot values for the range (PPMAPeriod) 54 | double sum = pivot; 55 | for (int i = 1; i < this.Period; i++) 56 | sum += this.GetPivotByOffset(i); 57 | 58 | this.SetValue(sum / this.Period, 1); 59 | } 60 | 61 | /// 62 | /// Compute pivot point value 63 | /// 64 | /// Historical offset 65 | /// Pivot point value 66 | private double GetPivotByOffset(int offset) => (this.High(offset) + this.Low(offset) + this.Close(offset)) / 3; 67 | } -------------------------------------------------------------------------------- /Indicators/IndicatorMomentum.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace Oscillators; 7 | 8 | public sealed class IndicatorMomentum : Indicator, IWatchlistIndicator 9 | { 10 | // Displays Input Parameter as input field (or checkbox if value type is bolean). 11 | [InputParameter("Period for Momentum", 0, 1, 999, 1, 0)] 12 | public int Period = 10; 13 | 14 | // Displays Input Parameter as dropdown list. 15 | [InputParameter("Sources prices for Momentum", 1, variants: new object[] { 16 | "Close", PriceType.Close, 17 | "Open", PriceType.Open, 18 | "High", PriceType.High, 19 | "Low", PriceType.Low, 20 | "Typical", PriceType.Typical, 21 | "Medium", PriceType.Median, 22 | "Weighted", PriceType.Weighted, 23 | "Volume", PriceType.Volume, 24 | "Open interest", PriceType.OpenInterest 25 | })] 26 | public PriceType SourcePrice = PriceType.Close; 27 | 28 | public int MinHistoryDepths => this.Period + 1; 29 | public override string ShortName => $"Momentum ({this.Period}: {this.SourcePrice})"; 30 | public override string HelpLink => "https://help.quantower.com/analytics-panels/chart/technical-indicators/oscillators/momentum"; 31 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorMomentum.cs"; 32 | 33 | /// 34 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 35 | /// 36 | public IndicatorMomentum() 37 | : base() 38 | { 39 | // Serves for an identification of related indicators with different parameters. 40 | this.Name = "Momentum"; 41 | this.Description = "Momentum compares where the current price is in relation to where the price was in the past."; 42 | 43 | // Defines line on demand with particular parameters. 44 | this.AddLineSeries("Momentum Line", Color.Blue, 1, LineStyle.Solid); 45 | this.AddLineLevel(0, "Threshold Line", Color.Gray, 1, LineStyle.Dot); 46 | 47 | this.SeparateWindow = true; 48 | } 49 | 50 | /// 51 | /// Calculation entry point. This function is called when a price data updates. 52 | /// Will be runing under the HistoricalBar mode during history loading. 53 | /// Under NewTick during realtime. 54 | /// Under NewBar if start of the new bar is required. 55 | /// 56 | /// Provides data of updating reason and incoming price. 57 | protected override void OnUpdate(UpdateArgs args) 58 | { 59 | if (this.Count < this.MinHistoryDepths) 60 | return; 61 | 62 | this.SetValue(this.GetPrice(this.SourcePrice) - this.GetPrice(this.SourcePrice, this.Period)); 63 | } 64 | } -------------------------------------------------------------------------------- /Indicators/IndicatorRelativeVigorIndex.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace OscillatorsIndicators; 7 | 8 | public class IndicatorRelativeVigorIndex : Indicator 9 | { 10 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorRelativeVigorIndex.cs"; 11 | 12 | public IndicatorRelativeVigorIndex() 13 | : base() 14 | { 15 | // Defines indicator's name and description. 16 | Name = "Relative Vigor Index"; 17 | Description = "Indicator measures the strength of a trend by comparing a security's closing price to its trading range while smoothing the results using a simple moving average."; 18 | 19 | // Defines line on demand with particular parameters. 20 | AddLineSeries("Signal line", Color.Red, 1, LineStyle.Solid); 21 | AddLineSeries("RVI line", Color.Green, 1, LineStyle.Solid); 22 | 23 | // By default indicator will be applied on main window of the chart 24 | SeparateWindow = true; 25 | } 26 | 27 | protected override void OnInit() 28 | { 29 | // Add your initialization code here 30 | } 31 | 32 | [InputParameter] 33 | public int Period = 2; 34 | protected override void OnUpdate(UpdateArgs args) 35 | { 36 | if (Count <= Period) 37 | return; 38 | SetValue(GetRVI(), 1); 39 | SetValue(GetSignalLine(), 0); 40 | } 41 | 42 | private double CloseMinusOpen(int index = 0) 43 | { 44 | return Close(index) - Open(index); 45 | } 46 | private double HightMinusLow(int index = 0) 47 | { 48 | return High(index) - Low(index); 49 | } 50 | private double Numerator(int index = 0) 51 | { 52 | double numerator = CloseMinusOpen(index) + 2 * CloseMinusOpen(index + 1) + 2 * CloseMinusOpen(index + 2) + CloseMinusOpen(index + 3); 53 | return numerator / 6; 54 | } 55 | private double Denominator(int index = 0) 56 | { 57 | double denominator = HightMinusLow(index) + 2 * HightMinusLow(index + 1) + 2 * HightMinusLow(index + 2) + HightMinusLow(index + 3); 58 | return denominator / 6; 59 | } 60 | private double GetRVI(int index = 0) 61 | { 62 | double numeratorSMA = 0; 63 | double denominatorSMA = 0; 64 | 65 | for (int i = 0; i < Period; i++) 66 | { 67 | numeratorSMA = numeratorSMA + Numerator(i + index); 68 | denominatorSMA = denominatorSMA + Denominator(i + index); 69 | } 70 | numeratorSMA = numeratorSMA / Period; 71 | denominatorSMA = denominatorSMA / Period; 72 | return numeratorSMA / denominatorSMA; 73 | } 74 | private double GetSignalLine() 75 | { 76 | double signalLine = 0; 77 | signalLine = GetRVI() + 2 * GetRVI(1) + 2 * GetRVI(2) + GetRVI(3); 78 | 79 | 80 | return signalLine / 6; 81 | } 82 | } -------------------------------------------------------------------------------- /Indicators/IndicatorSimpleMovingAverage.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using TradingPlatform.BusinessLayer; 4 | using System.Drawing; 5 | 6 | namespace MovingAverages; 7 | 8 | public sealed class IndicatorSimpleMovingAverage : Indicator, IWatchlistIndicator 9 | { 10 | // Displays Input Parameter as input field. 11 | [InputParameter("Period of Simple Moving Average", 0, 1, 9999, 1, 1)] 12 | public int Period = 20; 13 | 14 | // Displays Input Parameter as dropdown list. 15 | [InputParameter("Sources prices for MA", 1, variants: new object[]{ 16 | "Close", PriceType.Close, 17 | "Open", PriceType.Open, 18 | "High", PriceType.High, 19 | "Low", PriceType.Low, 20 | "Typical", PriceType.Typical, 21 | "Median", PriceType.Median, 22 | "Weighted", PriceType.Weighted, 23 | "Base asset volume", PriceType.Volume, 24 | "Quote asset volume", PriceType.QuoteAssetVolume, 25 | "Open interest", PriceType.OpenInterest 26 | })] 27 | public PriceType SourcePrice = PriceType.Close; 28 | 29 | public int MinHistoryDepths => this.Period; 30 | public override string ShortName => $"SMA ({this.Period}:{this.SourcePrice})"; 31 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorSimpleMovingAverage.cs"; 32 | 33 | /// 34 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 35 | /// 36 | public IndicatorSimpleMovingAverage() 37 | : base() 38 | { 39 | // Defines indicator's name and description. 40 | this.Name = "Simple Moving Average"; 41 | this.Description = "Average price for the last N periods"; 42 | 43 | // Define one line with particular parameters 44 | this.AddLineSeries("SMA", Color.Red, 1, LineStyle.Solid); 45 | 46 | this.SeparateWindow = false; 47 | } 48 | 49 | /// 50 | /// Calculation entry point. This function is called when a price data updates. 51 | /// Will be runing under the HistoricalBar mode during history loading. 52 | /// Under NewTick during realtime. 53 | /// Under NewBar if start of the new bar is required. 54 | /// 55 | /// Provides data of updating reason and incoming price. 56 | protected override void OnUpdate(UpdateArgs args) 57 | { 58 | // Checking, if current amount of bars 59 | // more, than period of moving average. If it is 60 | // then the calculation is possible 61 | if (this.Count < this.MinHistoryDepths) 62 | return; 63 | 64 | double sum = 0.0; // Sum of prices 65 | for (int i = 0; i < this.Period; i++) 66 | // Adding bar's price to the sum 67 | sum += this.GetPrice(this.SourcePrice, i); 68 | 69 | // Set value to the "SMA" line buffer. 70 | this.SetValue(sum / this.Period); 71 | } 72 | } -------------------------------------------------------------------------------- /Indicators/IndicatorFYL.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using TradingPlatform.BusinessLayer; 4 | using System.Drawing; 5 | 6 | namespace MovingAverages; 7 | 8 | #warning Не використовуйте абревіатури у назвах, особливо якщо якщо вони не загальноприйняті 9 | public sealed class IndicatorFYL : Indicator, IWatchlistIndicator 10 | { 11 | #region Parameters 12 | 13 | [InputParameter("Period of Linear Regression", 10, 2, 9999)] 14 | public int Period; 15 | 16 | [InputParameter("Sources prices for the regression line", 20, variants: new object[] { 17 | "Close", PriceType.Close, 18 | "Open", PriceType.Open, 19 | "High", PriceType.High, 20 | "Low", PriceType.Low, 21 | "Typical", PriceType.Typical, 22 | "Medium", PriceType.Median, 23 | "Weighted", PriceType.Weighted, 24 | "Volume", PriceType.Volume, 25 | "Open interest", PriceType.OpenInterest 26 | })] 27 | public PriceType SourcePrice; 28 | 29 | public int MinHistoryDepths => this.Period; 30 | public override string ShortName => $"FYL ({this.Period})"; 31 | 32 | private double sumX; 33 | private double divisor; 34 | 35 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorFYL.cs"; 36 | 37 | #endregion Parameters 38 | 39 | public IndicatorFYL() 40 | : base() 41 | { 42 | // Defines indicator's name and description. 43 | this.Name = "FYL"; 44 | this.Description = "Regression line"; 45 | 46 | this.Period = 20; 47 | this.SourcePrice = PriceType.Close; 48 | 49 | // By default indicator will be applied on main window of the chart 50 | this.SeparateWindow = false; 51 | 52 | // Defines line on demand with particular parameters. 53 | this.AddLineSeries("line1", Color.CadetBlue, 1, LineStyle.Solid); 54 | } 55 | 56 | protected override void OnInit() 57 | { 58 | this.sumX = (double)this.Period * (this.Period - 1) * 0.5; 59 | this.divisor = this.sumX * this.sumX - (double)this.Period * this.Period * (this.Period - 1) * (2 * this.Period - 1) / 6; 60 | } 61 | protected override void OnUpdate(UpdateArgs args) 62 | { 63 | //Проверяем что истории достаточно 64 | if (this.Count < this.MinHistoryDepths) 65 | { 66 | double price = this.GetPrice(this.SourcePrice); 67 | this.SetValue(price); 68 | return; 69 | } 70 | 71 | double sumY = 0.0; 72 | double sumXY = 0.0; 73 | 74 | // Calculation of sum 75 | for (int i = 0; i < this.Period; i++) 76 | { 77 | double price = this.GetPrice(this.SourcePrice, i); 78 | sumY += price; 79 | sumXY += i * price; 80 | } 81 | 82 | // Calculation of coefficients 83 | double a = (this.Period * sumXY - this.sumX * sumY) / this.divisor; 84 | double b = (sumY - a * this.sumX) / this.Period; 85 | 86 | // Setting of current value 87 | this.SetValue(a * (this.Period - 1) + b); 88 | } 89 | } -------------------------------------------------------------------------------- /Indicators/IndicatorAroon.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace Oscillators; 7 | 8 | public sealed class IndicatorAroon : Indicator, IWatchlistIndicator 9 | { 10 | // Displays Input Parameter as input field (or checkbox if value type is bolean). 11 | [InputParameter("AROON Period", 0, 1, 999, 1, 0)] 12 | public int Period = 14; 13 | 14 | public int MinHistoryDepths => this.Period; 15 | public override string ShortName => "AROON (" + this.Period + ")"; 16 | public override string HelpLink => "https://help.quantower.com/analytics-panels/chart/technical-indicators/oscillators/aroon-indicator"; 17 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorAroon.cs"; 18 | 19 | /// 20 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 21 | /// 22 | public IndicatorAroon() 23 | : base() 24 | { 25 | // Serves for an identification of related indicators with different parameters. 26 | this.Name = "Aroon"; 27 | this.Description = "Reveals the beginning of a new trend"; 28 | 29 | // Defines line on demand with particular parameters. 30 | this.AddLineSeries("Aroon up Line", Color.Blue, 1, LineStyle.Solid); 31 | this.AddLineSeries("Aroon down Line", Color.Blue, 1, LineStyle.Dot); 32 | this.AddLineLevel(70, "Upper Limit", Color.Red, 1, LineStyle.Solid); 33 | this.AddLineLevel(30, "Lower Limit", Color.Red, 1, LineStyle.Dot); 34 | 35 | this.SeparateWindow = true; 36 | } 37 | 38 | /// 39 | /// Calculation entry point. This function is called when a price data updates. 40 | /// Will be runing under the HistoricalBar mode during history loading. 41 | /// Under NewTick during realtime. 42 | /// Under NewBar if start of the new bar is required. 43 | /// 44 | /// Provides data of updating reason and incoming price. 45 | protected override void OnUpdate(UpdateArgs args) 46 | { 47 | if (this.Count < this.MinHistoryDepths) 48 | return; 49 | 50 | // Getting max and min prices for period 51 | double high = this.GetPrice(PriceType.High); 52 | double low = this.GetPrice(PriceType.Low); 53 | double perHigh = 0; 54 | double perLow = 0; 55 | for (int i = 1; i < this.Period; i++) 56 | { 57 | double price = this.GetPrice(PriceType.High, i); 58 | if (price > high) 59 | { 60 | high = price; 61 | perHigh = i; 62 | } 63 | 64 | price = this.GetPrice(PriceType.Low, i); 65 | if (price < low) 66 | { 67 | low = price; 68 | perLow = i; 69 | } 70 | } 71 | // Getting Aroon up and down lines 72 | this.SetValue((1.0 - perHigh / this.Period) * 100, 0); 73 | this.SetValue((1.0 - perLow / this.Period) * 100, 1); 74 | } 75 | } -------------------------------------------------------------------------------- /Indicators/IndicatorAwesomeOscillator.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace Oscillators; 7 | 8 | public sealed class IndicatorAwesomeOscillator : Indicator, IWatchlistIndicator 9 | { 10 | public int MinHistoryDepths => SLOW_PERIOD; 11 | public override string ShortName => "AO"; 12 | public override string HelpLink => "https://help.quantower.com/analytics-panels/chart/technical-indicators/oscillators/awesome-oscillator"; 13 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorAwesomeOscillator.cs"; 14 | 15 | private Indicator fastMA; 16 | private Indicator slowMA; 17 | 18 | // Fixed periods for SMA indicators. 19 | private const int FAST_PERIOD = 5; 20 | private const int SLOW_PERIOD = 34; 21 | 22 | /// 23 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 24 | /// 25 | public IndicatorAwesomeOscillator() 26 | : base() 27 | { 28 | // Defines indicator's name and description. 29 | this.Name = "Awesome Oscillator"; 30 | this.Description = "Awesome Oscillator determines market momentum"; 31 | 32 | // Defines line on demand with particular parameters. 33 | this.AddLineSeries("AO", Color.Gray, 2, LineStyle.Histogramm); 34 | this.SeparateWindow = true; 35 | } 36 | 37 | /// 38 | /// This function will be called after creating an indicator as well as after its input params reset or chart (symbol or timeframe) updates. 39 | /// 40 | protected override void OnInit() 41 | { 42 | // Get two SMA indicators from built-in indicator collection. 43 | this.fastMA = Core.Indicators.BuiltIn.SMA(FAST_PERIOD, PriceType.Median); 44 | this.slowMA = Core.Indicators.BuiltIn.SMA(SLOW_PERIOD, PriceType.Median); 45 | 46 | this.AddIndicator(this.fastMA); 47 | this.AddIndicator(this.slowMA); 48 | } 49 | 50 | /// 51 | /// Calculation entry point. This function is called when a price data updates. 52 | /// Will be runing under the HistoricalBar mode during history loading. 53 | /// Under NewTick during realtime. 54 | /// Under NewBar if start of the new bar is required. 55 | /// 56 | /// Provides data of updating reason and incoming price. 57 | protected override void OnUpdate(UpdateArgs args) 58 | { 59 | // Skip max period for correct calculation. 60 | if (this.Count < this.MinHistoryDepths) 61 | return; 62 | 63 | // Calculate the AO value 64 | double ao = this.fastMA.GetValue() - this.slowMA.GetValue(); 65 | double prevAO = double.IsNaN(this.GetValue(1)) 66 | ? this.GetPrice(PriceType.Close, 0) 67 | : this.GetValue(1); 68 | 69 | // Set values to 'AO' line buffer. 70 | this.SetValue(ao); 71 | 72 | var indicatorColor = (prevAO > ao) ? Color.Red : Color.Green; 73 | 74 | this.LinesSeries[0].SetMarker(0, indicatorColor); 75 | } 76 | } -------------------------------------------------------------------------------- /Indicators/IndicatorKairiRelativeIndex.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace Oscillators; 7 | 8 | /// 9 | /// Kairi Relative Index (KRI) calculates deviation of the current price from its simple moving average as a percent of the moving average. 10 | /// 11 | public sealed class IndicatorKairiRelativeIndex : Indicator, IWatchlistIndicator 12 | { 13 | // Displays Input Parameter as input field (or checkbox if value type is bolean). 14 | [InputParameter("Period", 0, 1, 999, 1, 0)] 15 | public int Period = 14; 16 | 17 | public int MinHistoryDepths => this.Period; 18 | public override string ShortName => $"KRI ({this.Period})"; 19 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorKairiRelativeIndex.cs"; 20 | 21 | // Holds simple moving average values. 22 | private Indicator sma; 23 | 24 | /// 25 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 26 | /// 27 | public IndicatorKairiRelativeIndex() 28 | : base() 29 | { 30 | // Defines indicator's group, name and description. 31 | this.Name = "Kairi Relative Index"; 32 | this.Description = "Kairi Relative Index (KRI) calculates deviation of the current price from its simple moving average as a percent of the moving average"; 33 | 34 | // Defines line and level on demand with particular parameters. 35 | this.AddLineSeries("KRI'Line", Color.Red, 1, LineStyle.Solid); 36 | this.AddLineLevel(0, "0'Line", Color.Gray, 1, LineStyle.Solid); 37 | 38 | this.SeparateWindow = true; 39 | } 40 | 41 | /// 42 | /// This function will be called after creating an indicator as well as after its input params reset or chart (symbol or timeframe) updates. 43 | /// 44 | protected override void OnInit() 45 | { 46 | // Creates an instance of the proper indicator (SMA) from the default indicators list. 47 | this.sma = Core.Indicators.BuiltIn.SMA(this.Period, PriceType.Close); 48 | // Adds an auxiliary (SMA) indicator to the current one (KRI). 49 | // This will let inner indicator (SMA) to be calculated in advance to the current one (KRI). 50 | this.AddIndicator(this.sma); 51 | } 52 | 53 | /// 54 | /// Calculation entry point. This function is called when a price data updates. 55 | /// Will be runing under the HistoricalBar mode during history loading. 56 | /// Under NewTick during realtime. 57 | /// Under NewBar if start of the new bar is required. 58 | /// 59 | /// Provides data of updating reason and incoming price. 60 | protected override void OnUpdate(UpdateArgs args) 61 | { 62 | // Checking, if current amount of bars less, than period of moving average - calculation is impossible. 63 | if (this.Count < this.Period) 64 | return; 65 | 66 | double val = this.sma.GetValue(); 67 | this.SetValue((this.GetPrice(PriceType.Close) - val) / val * 100); 68 | } 69 | } -------------------------------------------------------------------------------- /Indicators/IndicatorLinearlyWeightedMovingAverage.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using TradingPlatform.BusinessLayer; 4 | using System.Drawing; 5 | 6 | namespace MovingAverages; 7 | 8 | public sealed class IndicatorLinearlyWeightedMovingAverage : Indicator, IWatchlistIndicator 9 | { 10 | // Displays Input Parameter as dropdown list. 11 | [InputParameter("Period of LWMA", 0, 1, 9999, 1, 0)] 12 | public int Period = 20; 13 | 14 | // Displays Input Parameter as dropdown list. 15 | [InputParameter("Sources prices for LWMA", 1, variants: new object[] { 16 | "Close", PriceType.Close, 17 | "Open", PriceType.Open, 18 | "High", PriceType.High, 19 | "Low", PriceType.Low, 20 | "Typical", PriceType.Typical, 21 | "Medium", PriceType.Median, 22 | "Weighted", PriceType.Weighted, 23 | "Volume", PriceType.Volume, 24 | "Open interest", PriceType.OpenInterest 25 | })] 26 | public PriceType SourcePrice = PriceType.Close; 27 | 28 | public int MinHistoryDepths => this.Period; 29 | public override string ShortName => $"LWMA ({this.Period}: {this.SourcePrice})"; 30 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorLinearlyWeightedMovingAverage.cs"; 31 | 32 | /// 33 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 34 | /// 35 | public IndicatorLinearlyWeightedMovingAverage() 36 | : base() 37 | { 38 | // Serves for an identification of related indicators with different parameters. 39 | this.Name = "Linearly Weighted Moving Average"; 40 | this.Description = "The linear average price for the last N periods"; 41 | // Defines line on demand with particular parameters. 42 | this.AddLineSeries("LWMA line", Color.Blue, 1, LineStyle.Solid); 43 | 44 | this.SeparateWindow = false; 45 | } 46 | 47 | /// 48 | /// Calculation entry point. This function is called when a price data updates. 49 | /// Will be runing under the HistoricalBar mode during history loading. 50 | /// Under NewTick during realtime. 51 | /// Under NewBar if start of the new bar is required. 52 | /// 53 | /// Provides data of updating reason and incoming price. 54 | protected override void OnUpdate(UpdateArgs args) 55 | { 56 | if (this.Count > this.MinHistoryDepths) 57 | { 58 | double numerator = 0.0; 59 | double denominator = 0.0; 60 | 61 | for (int i = 0; i < this.Period; i++) 62 | { 63 | int weight = this.Period - i; 64 | // Calculation of a coefficient 65 | numerator += weight * this.GetPrice(this.SourcePrice, i); 66 | // Calculation of a coefficient 67 | denominator += weight; 68 | } 69 | this.SetValue(denominator != 0D ? numerator / denominator : 0D); 70 | } 71 | else 72 | { 73 | double price = this.GetPrice(this.SourcePrice); 74 | this.SetValue(price); 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /Indicators/IndicatorHullMovingAverage.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System; 4 | using System.Drawing; 5 | using TradingPlatform.BusinessLayer; 6 | 7 | namespace MovingAverageIndicators; 8 | 9 | public class IndicatorHullMovingAverage : Indicator, IWatchlistIndicator 10 | { 11 | #region Parameters 12 | 13 | // Period of moving average. 14 | [InputParameter("Period of Hull Moving Average", 10, 1, 9999, 1, 0)] 15 | public int MaPeriod = 9; 16 | 17 | // Price type of moving average. 18 | [InputParameter("Sources prices for MA", 20, variants: new object[] 19 | { 20 | "Close", PriceType.Close, 21 | "Open", PriceType.Open, 22 | "High", PriceType.High, 23 | "Low", PriceType.Low, 24 | "Typical", PriceType.Typical, 25 | "Median", PriceType.Median, 26 | "Weighted", PriceType.Weighted, 27 | })] 28 | public PriceType SourcePrice = PriceType.Close; 29 | 30 | public override string ShortName => $"HMA ({this.MaPeriod}; {this.SourcePrice})"; 31 | 32 | private HistoricalDataCustom hullWMASource; 33 | 34 | private Indicator fullWMA; 35 | private Indicator halfWMA; 36 | private Indicator wma; 37 | 38 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorHullMovingAverage.cs"; 39 | 40 | #endregion Parameters 41 | 42 | #region IWatchlistIndicator 43 | 44 | public int MinHistoryDepths => this.MaPeriod; 45 | 46 | #endregion IWatchlistIndicator 47 | 48 | public IndicatorHullMovingAverage() 49 | { 50 | this.Name = "Hull Moving Average"; 51 | this.AddLineSeries("HMA", Color.Orange, 2, LineStyle.Dash); 52 | this.SeparateWindow = false; 53 | } 54 | 55 | #region Overrides 56 | 57 | protected override void OnInit() 58 | { 59 | this.fullWMA = Core.Instance.Indicators.BuiltIn.LWMA(this.MaPeriod, this.SourcePrice); 60 | this.halfWMA = Core.Instance.Indicators.BuiltIn.LWMA(this.MaPeriod / 2, this.SourcePrice); 61 | this.wma = Core.Instance.Indicators.BuiltIn.LWMA((int)Math.Floor(Math.Sqrt(this.MaPeriod)), PriceType.Close); 62 | 63 | this.hullWMASource = new HistoricalDataCustom(this); 64 | this.hullWMASource.AddIndicator(this.wma); 65 | 66 | this.AddIndicator(this.fullWMA); 67 | this.AddIndicator(this.halfWMA); 68 | } 69 | protected override void OnUpdate(UpdateArgs args) 70 | { 71 | if (this.Count < this.MaPeriod) 72 | return; 73 | double hullMWASourceValue = 2 * this.halfWMA.GetValue() - this.fullWMA.GetValue(); 74 | this.hullWMASource.SetValue(0d, 0d, 0d, hullMWASourceValue); 75 | this.SetValue(this.wma.GetValue()); 76 | } 77 | protected override void OnClear() 78 | { 79 | if (this.hullWMASource != null) 80 | { 81 | this.hullWMASource.RemoveIndicator(this.wma); 82 | this.hullWMASource.Dispose(); 83 | } 84 | 85 | if (this.fullWMA != null) 86 | this.RemoveIndicator(this.fullWMA); 87 | 88 | if (this.halfWMA != null) 89 | this.RemoveIndicator(this.halfWMA); 90 | } 91 | 92 | #endregion Overrides 93 | } -------------------------------------------------------------------------------- /Indicators/IndicatorChandeMomentumOscillator.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace Volatility; 7 | 8 | public sealed class IndicatorChandeMomentumOscillator : Indicator, IWatchlistIndicator 9 | { 10 | // Displays Input Parameter as input field. 11 | [InputParameter("Period of MA for envelopes", 0, 1, 999, 1, 0)] 12 | public int Period = 9; 13 | 14 | // Displays Input Parameter as dropdown list. 15 | [InputParameter("Sources prices for MA", 1, variants: new object[] { 16 | "Close", PriceType.Close, 17 | "Open", PriceType.Open, 18 | "High", PriceType.High, 19 | "Low", PriceType.Low, 20 | "Typical", PriceType.Typical, 21 | "Medium", PriceType.Median, 22 | "Weighted", PriceType.Weighted, 23 | "Volume", PriceType.Volume, 24 | "Open interest", PriceType.OpenInterest 25 | })] 26 | public PriceType SourcePrice = PriceType.Close; 27 | 28 | public int MinHistoryDepths => this.Period + 1; 29 | public override string ShortName => $"CMO ({this.Period}: {this.SourcePrice})"; 30 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorChandeMomentumOscillator.cs"; 31 | 32 | /// 33 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 34 | /// 35 | public IndicatorChandeMomentumOscillator() 36 | : base() 37 | { 38 | // Defines indicator's name and description. 39 | this.Name = "Chande Momentum Oscillator"; 40 | this.Description = "Calculates the dividing of difference between the sum of all recent gains and the sum of all recent losses by the sum of all price movement over the period."; 41 | 42 | // Defines line on demand with particular parameters. 43 | this.AddLineSeries("CMO", Color.Purple, 2, LineStyle.Solid); 44 | this.AddLineLevel(50, "Up", Color.Blue, 1, LineStyle.Dash); 45 | this.AddLineLevel(-50, "Down", Color.Blue, 1, LineStyle.Dash); 46 | this.SeparateWindow = true; 47 | } 48 | 49 | /// 50 | /// Calculation entry point. This function is called when a price data updates. 51 | /// Will be runing under the HistoricalBar mode during history loading. 52 | /// Under NewTick during realtime. 53 | /// Under NewBar if start of the new bar is required. 54 | /// 55 | /// Provides data of updating reason and incoming price. 56 | protected override void OnUpdate(UpdateArgs args) 57 | { 58 | // Skip some period for correct calculation. 59 | if (this.Count < this.MinHistoryDepths) 60 | return; 61 | 62 | // Calculate the sum 63 | double sum1 = 0d; 64 | double sum2 = 0d; 65 | for (int i = 0; i < this.Period; i++) 66 | { 67 | double diff = this.GetPrice(this.SourcePrice, i) - this.GetPrice(this.SourcePrice, i + 1); 68 | if (diff > 0) 69 | sum1 += diff; 70 | else 71 | sum2 -= diff; 72 | } 73 | 74 | // Compute the cmo value and set its to the 'CMO' line. 75 | this.SetValue(100.0 * ((sum1 - sum2) / (sum1 + sum2))); 76 | } 77 | } -------------------------------------------------------------------------------- /Indicators/IndicatorBandas.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace OscillatorsIndicators; 7 | 8 | public class IndicatorBandas : Indicator 9 | { 10 | #region Parameters 11 | [InputParameter("Period", 10, 1, 99999, 1, 0)] 12 | public int Period = 52; 13 | 14 | [InputParameter("Distance", 20, 0.1, 99999, 0.1, 1)] 15 | public double Distance = 3.5; 16 | 17 | [InputParameter("Sources prices", 30, variants: new object[]{ 18 | "Close", PriceType.Close, 19 | "Open", PriceType.Open, 20 | "High", PriceType.High, 21 | "Low", PriceType.Low, 22 | "Typical", PriceType.Typical, 23 | "Medium", PriceType.Median, 24 | "Weighted", PriceType.Weighted, 25 | "Volume", PriceType.Volume, 26 | "Open interest", PriceType.OpenInterest 27 | })] 28 | public PriceType SourcePrice = PriceType.Close; 29 | 30 | [InputParameter("Type of middle moving average", 40, variants: new object[]{ 31 | "Simple Moving Average", MaMode.SMA, 32 | "Exponential Moving Average", MaMode.EMA, 33 | "Smoothed Moving Average", MaMode.SMMA, 34 | "Linearly Weighted Moving Average", MaMode.LWMA, 35 | })] 36 | public MaMode MaType = MaMode.EMA; 37 | 38 | public override string ShortName => $"{this.Name} ({this.Period}: {this.Distance})"; 39 | 40 | private HistoricalDataCustom customHD; 41 | private Indicator diffMA; 42 | private Indicator middleMA; 43 | 44 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorBandas.cs"; 45 | 46 | #endregion Parameters 47 | 48 | public IndicatorBandas() 49 | { 50 | this.Name = "Bandas"; 51 | 52 | this.AddLineSeries("Middle", Color.Orange, 1, LineStyle.Solid); 53 | this.AddLineSeries("Upper", Color.DodgerBlue, 1, LineStyle.Solid); 54 | this.AddLineSeries("Lower", Color.DodgerBlue, 1, LineStyle.Solid); 55 | 56 | this.SeparateWindow = false; 57 | } 58 | 59 | #region Overrides 60 | protected override void OnInit() 61 | { 62 | this.customHD = new HistoricalDataCustom(this); 63 | this.diffMA = Core.Indicators.BuiltIn.EMA(this.Period, this.SourcePrice); 64 | this.customHD.AddIndicator(this.diffMA); 65 | 66 | this.middleMA = Core.Indicators.BuiltIn.MA(this.Period, PriceType.Typical, this.MaType); 67 | this.AddIndicator(this.middleMA); 68 | } 69 | protected override void OnUpdate(UpdateArgs args) 70 | { 71 | var diff = this.High() - this.Low(); 72 | this.customHD.SetValue(0, 0, 0, diff); 73 | 74 | if (this.Count < this.Period) 75 | return; 76 | 77 | var middle = this.middleMA.GetValue(); 78 | var offset = this.diffMA.GetValue() * this.Distance; 79 | 80 | this.SetValue(middle, 0); 81 | this.SetValue(middle + offset, 1); 82 | this.SetValue(middle - offset, 2); 83 | } 84 | protected override void OnClear() 85 | { 86 | this.customHD.RemoveIndicator(this.diffMA); 87 | this.customHD.Dispose(); 88 | this.diffMA.Dispose(); 89 | 90 | this.RemoveIndicator(this.middleMA); 91 | this.middleMA.Dispose(); 92 | } 93 | #endregion Overrides 94 | } -------------------------------------------------------------------------------- /Indicators/IndicatorBBS.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace ChanneIsIndicators; 7 | 8 | #warning Не використовуйте абревіатури у назвах, особливо якщо якщо вони не загальноприйняті 9 | public sealed class IndicatorBBS : Indicator 10 | { 11 | [InputParameter("Fast period", 10, 1, 99999, 1, 0)] 12 | public int FastPeriod; 13 | 14 | [InputParameter("Slow period", 20, 1, 99999, 1, 0)] 15 | public int SlowPeriod; 16 | 17 | [InputParameter("Smooth period", 30, 1, 99999, 1, 0)] 18 | public int SmoothPeriod; 19 | 20 | [InputParameter("Period", 10, 1, 99999, 1, 0)] 21 | public int Period; 22 | 23 | [InputParameter("STD num", 10, 1, 99999, 1, 0)] 24 | public int STDNum; 25 | 26 | public override string ShortName => $"{this.Name} ({this.FastPeriod}: {this.SlowPeriod}: {this.SmoothPeriod}: {this.Period}: {this.STDNum})"; 27 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorBBS.cs"; 28 | 29 | private double c1; 30 | private double c2; 31 | private double c3; 32 | private double c4; 33 | 34 | private double fastValue; 35 | private double slowValue; 36 | private double prevFastValue; 37 | private double prevSlowValue; 38 | 39 | public IndicatorBBS() 40 | { 41 | this.Name = "BBS"; 42 | 43 | this.FastPeriod = 12; 44 | this.SlowPeriod = 26; 45 | this.SmoothPeriod = 5; 46 | this.Period = 10; 47 | this.STDNum = 1; 48 | 49 | this.SeparateWindow = true; 50 | 51 | this.AddLineSeries("BBSNUM", Color.Orange, 1, LineStyle.Points); 52 | 53 | this.AddLineLevel(0.3, "Up level", Color.Gray, 1, LineStyle.Dot); 54 | this.AddLineLevel(0, "Middle level", Color.Gray, 1, LineStyle.Dot); 55 | this.AddLineLevel(-0.3, "Down level", Color.Gray, 1, LineStyle.Dot); 56 | } 57 | 58 | protected override void OnInit() 59 | { 60 | base.OnInit(); 61 | 62 | this.c1 = 2.0 / (1 + this.FastPeriod); 63 | this.c2 = 1 - this.c1; 64 | this.c3 = 2.0 / (1 + this.SlowPeriod); 65 | this.c4 = 1 - this.c3; 66 | } 67 | 68 | protected override void OnUpdate(UpdateArgs args) 69 | { 70 | double price = this.Close(); 71 | 72 | if (this.Count == 1) 73 | { 74 | this.fastValue = price; 75 | this.slowValue = price; 76 | 77 | this.SetValue(0); 78 | } 79 | else 80 | { 81 | if (args.Reason == UpdateReason.HistoricalBar || args.Reason == UpdateReason.NewBar) 82 | { 83 | this.prevFastValue = this.fastValue; 84 | this.prevSlowValue = this.slowValue; 85 | } 86 | 87 | this.fastValue = this.c1 * price + this.c2 * this.prevFastValue; 88 | this.slowValue = this.c3 * price + this.c4 * this.prevSlowValue; 89 | 90 | double bbsnum = this.fastValue - this.slowValue; 91 | 92 | this.SetValue(bbsnum); 93 | } 94 | } 95 | 96 | protected override void OnClear() 97 | { 98 | this.prevFastValue = 0; 99 | this.prevSlowValue = 0; 100 | 101 | base.OnClear(); 102 | } 103 | } -------------------------------------------------------------------------------- /Indicators/IndicatorPolynomialRegressionChannel.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using MathNet.Numerics; 4 | using MathNet.Numerics.Statistics; 5 | using System; 6 | using System.Drawing; 7 | using TradingPlatform.BusinessLayer; 8 | 9 | namespace Channels; 10 | 11 | public sealed class IndicatorPolynomialRegressionChannel : Indicator 12 | { 13 | [InputParameter("Period of Hull Moving Average", 10, 1, 9999, 1, 0)] 14 | public int MaPeriod; 15 | 16 | /// 17 | /// Price type of moving average. 18 | /// 19 | [InputParameter("Sources prices for MA", 20, variants: new object[] 20 | { 21 | "Close", PriceType.Close, 22 | "Open", PriceType.Open, 23 | "High", PriceType.High, 24 | "Low", PriceType.Low, 25 | "Typical", PriceType.Typical, 26 | "Medium", PriceType.Median, 27 | "Weighted", PriceType.Weighted, 28 | })] 29 | public PriceType SourcePrice; 30 | 31 | [InputParameter("Type of moving average", 3, variants: new object[]{ 32 | "Simple Moving Average", MaMode.SMA, 33 | "Exponential Moving Average", MaMode.EMA, 34 | "Smoothed Moving Average", MaMode.SMMA, 35 | "Linearly Weighted Moving Average", MaMode.LWMA, 36 | })] 37 | public MaMode MaType; 38 | 39 | [InputParameter("Polynomial degree", 10, 1, 9999, 1, 0)] 40 | public int polynomialDegree; 41 | 42 | private Indicator ma; 43 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorPolynomialRegressionChannel.cs"; 44 | public IndicatorPolynomialRegressionChannel() 45 | : base() 46 | { 47 | this.Name = "Polynomial Regression Channel"; 48 | this.SeparateWindow = false; 49 | this.MaPeriod = 20; 50 | this.SourcePrice = PriceType.Close; 51 | this.MaType = MaMode.SMA; 52 | this.polynomialDegree = 2; 53 | 54 | this.AddLineSeries("Upper Band", Color.Green, 1, LineStyle.Solid); 55 | this.AddLineSeries("Lower Band", Color.Red, 1, LineStyle.Solid); 56 | this.AddLineSeries("Regression", Color.CadetBlue, 1, LineStyle.Solid); 57 | } 58 | protected override void OnInit() 59 | { 60 | this.ma = Core.Instance.Indicators.BuiltIn.MA(this.MaPeriod, this.SourcePrice, this.MaType); 61 | this.AddIndicator(this.ma); 62 | } 63 | protected override void OnUpdate(UpdateArgs args) 64 | { 65 | double[] xData = new double[this.MaPeriod]; 66 | double[] yData = new double[this.MaPeriod]; 67 | for (int i = 0; i < this.MaPeriod; i++) 68 | { 69 | xData[i] = i; 70 | yData[i] = this.ma.GetValue(i); 71 | } 72 | 73 | double[] coefficients = Fit.Polynomial(xData, yData, this.polynomialDegree); 74 | double[] predictedValues = new double[this.MaPeriod]; 75 | for (int i = 0; i < this.MaPeriod; i++) 76 | { 77 | double predictedValue = 0; 78 | for (int j = 0; j <= this.polynomialDegree; j++) 79 | predictedValue += coefficients[j] * Math.Pow(i, j); 80 | 81 | predictedValues[i] = predictedValue; 82 | } 83 | 84 | double stdDev = Statistics.StandardDeviation(predictedValues); 85 | this.SetValue(predictedValues[0] + 2 * stdDev, 0); 86 | this.SetValue(predictedValues[0] - 2 * stdDev, 1); 87 | this.SetValue(predictedValues[0], 2); 88 | } 89 | } -------------------------------------------------------------------------------- /Indicators/IndicatorPositiveVolumeIndex.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace Volume; 7 | 8 | /// 9 | /// Changes on the periods in which value of volume has increased in comparison with the previous period. 10 | /// 11 | public sealed class IndicatorPositiveVolumeIndex : Indicator, IWatchlistIndicator 12 | { 13 | private const int MIN_PERIOD = 1; 14 | 15 | // Displays Input Parameter as dropdown list. 16 | [InputParameter("Source price", 0, variants: new object[] { 17 | "Close", PriceType.Close, 18 | "Open", PriceType.Open, 19 | "High", PriceType.High, 20 | "Low", PriceType.Low, 21 | "Typical", PriceType.Typical, 22 | "Medium", PriceType.Median, 23 | "Weighted", PriceType.Weighted, 24 | "Volume", PriceType.Volume, 25 | "Open interest", PriceType.OpenInterest 26 | })] 27 | public PriceType SourcePrice = PriceType.Close; 28 | 29 | public int MinHistoryDepths => MIN_PERIOD; 30 | public override string ShortName => $"PVI ({this.SourcePrice})"; 31 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorPositiveVolumeIndex.cs"; 32 | 33 | // Keeps previous volume, price and PVI values. 34 | private double prevVolume = 0; 35 | private double prevPrice = 0; 36 | private double prevPVI = 1; 37 | 38 | /// 39 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 40 | /// 41 | public IndicatorPositiveVolumeIndex() 42 | : base() 43 | { 44 | // Defines indicator's group, name and description. 45 | this.Name = "Positive Volume Index"; 46 | this.Description = "Changes on the periods in which value of volume has increased in comparison with the previous period."; 47 | 48 | // Defines line on demand with particular parameters. 49 | this.AddLineSeries("PVI'Line", Color.Blue, 1, LineStyle.Solid); 50 | 51 | this.SeparateWindow = true; 52 | } 53 | 54 | /// 55 | /// Calculation entry point. This function is called when a price data updates. 56 | /// Will be runing under the HistoricalBar mode during history loading. 57 | /// Under NewTick during realtime. 58 | /// Under NewBar if start of the new bar is required. 59 | /// 60 | /// Provides data of updating reason and incoming price. 61 | protected override void OnUpdate(UpdateArgs args) 62 | { 63 | if (this.Count < this.MinHistoryDepths) 64 | return; 65 | 66 | double volume = this.Volume(); 67 | // If symbol type or chart aggregation doesn't provide volumes - use ticks value. 68 | double curVolume = (double.IsNaN(volume) || volume == 0) ? this.Ticks() : volume; 69 | 70 | double curPrice = this.GetPrice(this.SourcePrice, 0); 71 | double curPVI = (curVolume > this.prevVolume && this.prevPrice != 0) ? this.prevPVI + this.prevPVI * (curPrice - this.prevPrice) / this.prevPrice : this.prevPVI; 72 | 73 | this.SetValue(curPVI); 74 | 75 | // Save state. 76 | if (args.Reason != UpdateReason.NewTick) 77 | { 78 | this.prevVolume = curVolume; 79 | this.prevPrice = curPrice; 80 | this.prevPVI = curPVI; 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /Indicators/IndicatorModifiedMovingAverage.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace MovingAverages; 7 | 8 | /// 9 | /// Modified Moving Average comprises a sloping factor to help it overtake with the growing or declining value of the trading price of the currency. 10 | /// 11 | public sealed class IndicatorModifiedMovingAverage : Indicator, IWatchlistIndicator 12 | { 13 | // Displays Input Parameter as input field (or checkbox if value type is bolean). 14 | [InputParameter("Period of Modified Moving Average", 0, 1, 9999)] 15 | public int Period = 20; 16 | 17 | // Displays Input Parameter as dropdown list. 18 | [InputParameter("Sources prices for MA", 1, variants: new object[] { 19 | "Close", PriceType.Close, 20 | "Open", PriceType.Open, 21 | "High", PriceType.High, 22 | "Low", PriceType.Low, 23 | "Typical", PriceType.Typical, 24 | "Medium", PriceType.Median, 25 | "Weighted", PriceType.Weighted, 26 | "Volume", PriceType.Volume, 27 | "Open interest", PriceType.OpenInterest 28 | })] 29 | public PriceType SourcePrice = PriceType.Close; 30 | 31 | public int MinHistoryDepths => this.Period; 32 | public override string ShortName => $"MMA ({this.Period}: {this.SourcePrice})"; 33 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorModifiedMovingAverage.cs"; 34 | 35 | // Calculation coefficient. 36 | private double coeff; 37 | 38 | /// 39 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 40 | /// 41 | public IndicatorModifiedMovingAverage() 42 | : base() 43 | { 44 | // Defines indicator's group, name and description. 45 | this.Name = "Modified Moving Average"; 46 | this.Description = "Modified Moving Average comprises a sloping factor to help it overtake with the growing or declining value of the trading price of the currency."; 47 | 48 | // Defines line on demand with particular parameters. 49 | this.AddLineSeries("MMA", Color.DodgerBlue, 1, LineStyle.Solid); 50 | 51 | this.SeparateWindow = false; 52 | } 53 | 54 | /// 55 | /// This function will be called after creating an indicator as well as after its input params reset or chart (symbol or timeframe) updates. 56 | /// 57 | protected override void OnInit() 58 | { 59 | //coefficient calculating 60 | this.coeff = 1.0d / this.Period; 61 | } 62 | 63 | /// 64 | /// Calculation entry point. This function is called when a price data updates. 65 | /// Will be running under the HistoricalBar mode during history loading. 66 | /// Under NewTick during real time. 67 | /// Under NewBar if start of the new bar is required. 68 | /// 69 | /// Provides data of updating reason and incoming price. 70 | protected override void OnUpdate(UpdateArgs args) 71 | { 72 | // Checking, if current amount of bars less, than period of moving average - calculation is impossible. 73 | if (this.Count < this.MinHistoryDepths) 74 | return; 75 | 76 | // Value calculation. 77 | double mma = this.GetPrice(this.SourcePrice); 78 | 79 | for (int i = 0; i < this.Period; i++) 80 | { 81 | double price = this.GetPrice(this.SourcePrice, i); 82 | mma = price * this.coeff + mma * (1.0 - this.coeff); 83 | } 84 | 85 | // Displaying value on the chart. 86 | this.SetValue(mma); 87 | } 88 | } -------------------------------------------------------------------------------- /Indicators/IndicatorMoneyFlowIndex.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Collections.Generic; 4 | using System.Drawing; 5 | using System.Linq; 6 | using TradingPlatform.BusinessLayer; 7 | 8 | namespace Volume; 9 | 10 | public sealed class IndicatorMoneyFlowIndex : Indicator, IWatchlistIndicator 11 | { 12 | // Displays Input Parameter as input field. 13 | [InputParameter("MFI Period", 0, 2, 999, 1, 0)] 14 | public int Period = 14; 15 | 16 | private readonly List fpmf; 17 | private readonly List fnmf; 18 | 19 | public int MinHistoryDepths => this.Period; 20 | public override string ShortName => $"MFI ({this.Period})"; 21 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorMoneyFlowIndex.cs"; 22 | 23 | /// 24 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 25 | /// 26 | public IndicatorMoneyFlowIndex() 27 | : base() 28 | { 29 | this.fpmf = new List(); 30 | this.fnmf = new List(); 31 | 32 | // Defines indicator's name and description. 33 | this.Name = "Money Flow Index"; 34 | this.Description = "The Money Flow Index (MFI) is an oscillator that uses both price and volume to measure buying and selling pressure"; 35 | 36 | // Defines lines on demand with particular parameters. 37 | this.AddLineSeries("MFI", Color.Orange, 1, LineStyle.Solid); 38 | this.AddLineLevel(80d, "Up", Color.Gray, 1, LineStyle.Dot); 39 | this.AddLineLevel(20d, "Down", Color.Gray, 1, LineStyle.Dot); 40 | 41 | this.SeparateWindow = true; 42 | } 43 | 44 | /// 45 | /// Calculation entry point. This function is called when a price data updates. 46 | /// Will be runing under the HistoricalBar mode during history loading. 47 | /// Under NewTick during realtime. 48 | /// Under NewBar if start of the new bar is required. 49 | /// 50 | /// Provides data of updating reason and incoming price. 51 | protected override void OnUpdate(UpdateArgs args) 52 | { 53 | // Insert new item to collections only on HistoricalBar of NewBar. 54 | if (args.Reason != UpdateReason.NewTick) 55 | { 56 | this.fnmf.Insert(0, 0); 57 | this.fpmf.Insert(0, 0); 58 | } 59 | // Skip the bar at the beginning of the story. 60 | if (this.Count == 1) 61 | return; 62 | 63 | // Get current and previous typical prices. 64 | double curPrice = this.GetPrice(PriceType.Typical, 0); 65 | double prevPrice = this.GetPrice(PriceType.Typical, 1); 66 | 67 | // Try to get volume value. If it's '0' or 'NaN' then get ticks value. 68 | double vol = (this.Volume() == 0 || double.IsNaN(this.Volume())) ? this.Ticks() : this.Volume(); 69 | if (double.IsNaN(vol) || vol == 0) 70 | return; 71 | 72 | // Populate collections. 73 | if (curPrice > prevPrice) 74 | this.fpmf[0] = curPrice * vol; 75 | else if (curPrice < prevPrice) 76 | this.fnmf[0] = curPrice * vol; 77 | 78 | // Skip some period for correct calculation. 79 | if (this.Count < this.MinHistoryDepths) 80 | return; 81 | 82 | // Get the sum of values for the specific interval. 83 | double pmf = this.fpmf.Take(this.Period).Sum(); 84 | double nmf = this.fnmf.Take(this.Period).Sum(); 85 | 86 | // Set value to the "MFI" line buffer. 87 | if (nmf != 0.0 && pmf != -nmf) 88 | this.SetValue(100.0 - 100.0 / (1.0 + pmf / nmf)); 89 | else 90 | this.SetValue(100.0); 91 | } 92 | } -------------------------------------------------------------------------------- /Indicators/IndicatorDeltaDivergenceReversal.cs: -------------------------------------------------------------------------------- 1 | 2 | // Copyright QUANTOWER LLC. © 2017-2021. All rights reserved. 3 | 4 | using System.Collections.Generic; 5 | using System.Drawing; 6 | using TradingPlatform.BusinessLayer; 7 | 8 | namespace OscillatorsIndicators; 9 | 10 | public class IndicatorDeltaDivergenceReversal : Indicator, IVolumeAnalysisIndicator 11 | { 12 | private Color buyColor = Color.Green; 13 | private Color sellColor = Color.Red; 14 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorDeltaDivergenceReversal.cs"; 15 | 16 | public IndicatorDeltaDivergenceReversal() 17 | : base() 18 | { 19 | Name = "Delta Divergence Reversal"; 20 | 21 | AddLineSeries("Low", Color.CadetBlue, 1, LineStyle.Points); 22 | AddLineSeries("High", Color.IndianRed, 1, LineStyle.Points); 23 | 24 | SeparateWindow = false; 25 | } 26 | public bool IsRequirePriceLevelsCalculation => false; 27 | 28 | public void VolumeAnalysisData_Loaded() 29 | { 30 | for (int i = 0; i < this.Count - 1; i++) 31 | DrawMarkers(i); 32 | } 33 | 34 | protected override void OnUpdate(UpdateArgs args) 35 | { 36 | SetValue(High(), 1); 37 | SetValue(Low(), 0); 38 | if (this.HistoricalData.VolumeAnalysisCalculationProgress == null || this.HistoricalData.VolumeAnalysisCalculationProgress.State != VolumeAnalysisCalculationState.Finished) 39 | return; 40 | DrawMarkers(); 41 | } 42 | 43 | private void DrawMarkers(int offset = 0) 44 | { 45 | var currentItem = this.HistoricalData[offset]; 46 | if (currentItem.VolumeAnalysisData == null) 47 | return; 48 | 49 | var previousItem = this.HistoricalData[offset + 1]; 50 | double delta = currentItem.VolumeAnalysisData.Total.Delta; 51 | double currentHigh = ((HistoryItemBar)currentItem).High; 52 | double previousHigh = ((HistoryItemBar)previousItem).High; 53 | double currentLow = ((HistoryItemBar)currentItem).Low; 54 | double previousLow = ((HistoryItemBar)previousItem).Low; 55 | 56 | if ((currentHigh > previousHigh && currentLow > previousLow) && delta < 0) 57 | LinesSeries[1].SetMarker(offset, new IndicatorLineMarker(sellColor, upperIcon: IndicatorLineMarkerIconType.DownArrow)); 58 | else if ((currentHigh < previousHigh && currentLow < previousLow) && delta >= 0) 59 | LinesSeries[0].SetMarker(offset, new IndicatorLineMarker(buyColor, bottomIcon: IndicatorLineMarkerIconType.UpArrow)); 60 | else 61 | { 62 | LinesSeries[0].RemoveMarker(offset); 63 | LinesSeries[1].RemoveMarker(offset); 64 | } 65 | } 66 | 67 | public override IList Settings 68 | { 69 | get 70 | { 71 | var settings = base.Settings; 72 | settings.Add(new SettingItemColor("BuyColor", this.buyColor) 73 | { 74 | Text = "Buy Color" 75 | }); 76 | settings.Add(new SettingItemColor("SellColor", this.sellColor) 77 | { 78 | Text = "Sell Color" 79 | }); 80 | return settings; 81 | } 82 | set 83 | { 84 | base.Settings = value; 85 | if (value.TryGetValue("BuyColor", out Color buyColor)) 86 | this.buyColor = buyColor; 87 | if (value.TryGetValue("SellColor", out Color sellColor)) 88 | this.sellColor = sellColor; 89 | OnSettingsUpdated(); 90 | } 91 | } 92 | protected override void OnSettingsUpdated() 93 | { 94 | base.OnSettingsUpdated(); 95 | for (int i = 0; i < this.Count - 1; i++) 96 | DrawMarkers(i); 97 | } 98 | } -------------------------------------------------------------------------------- /Indicators/IndicatorSuperTrend.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace TrendIndicators; 7 | 8 | public class IndicatorSuperTrend : Indicator, IWatchlistIndicator 9 | { 10 | #region Parameters 11 | [InputParameter("ATR period", 0, 1, 999, 1, 0)] 12 | public int AtrPeriod = 10; 13 | [InputParameter("Digit", 1, 0.01, 10, 0.01, 2)] 14 | public double Digit = 3; 15 | [InputParameter("Up trend color", 3)] 16 | public Color UpTrendColor = Color.Green; 17 | [InputParameter("Down trend color", 3)] 18 | public Color DownTrendColor = Color.Red; 19 | 20 | public override string ShortName => $"ST ({this.AtrPeriod}: {this.Digit})"; 21 | 22 | public int MinHistoryDepths => this.AtrPeriod; 23 | 24 | private Indicator atrIndicator; 25 | private int prevTrend; 26 | private double prevDown; 27 | private double prevUP; 28 | private double down; 29 | private double up; 30 | private int currTrend; 31 | 32 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorSuperTrend.cs"; 33 | 34 | #endregion Parameters 35 | 36 | public IndicatorSuperTrend() 37 | { 38 | this.Name = "SuperTrend"; 39 | this.AddLineSeries("ST line", Color.DodgerBlue, 2, LineStyle.Solid); 40 | this.SeparateWindow = false; 41 | } 42 | 43 | protected override void OnInit() 44 | { 45 | base.OnInit(); 46 | this.atrIndicator = Core.Indicators.BuiltIn.ATR(this.AtrPeriod, MaMode.SMA); 47 | this.AddIndicator(this.atrIndicator); 48 | } 49 | 50 | protected override void OnUpdate(UpdateArgs args) 51 | { 52 | base.OnUpdate(args); 53 | 54 | if (this.Count < this.AtrPeriod) 55 | return; 56 | 57 | var isNewBar = false; 58 | if (this.HistoricalData.Aggregation is HistoryAggregationTick) 59 | isNewBar = args.Reason == UpdateReason.NewTick || args.Reason == UpdateReason.HistoricalBar; 60 | else 61 | isNewBar = args.Reason == UpdateReason.NewBar || args.Reason == UpdateReason.HistoricalBar; 62 | 63 | if (isNewBar) 64 | { 65 | this.prevDown = this.up; 66 | this.prevTrend = this.currTrend; 67 | this.prevUP = this.down; 68 | } 69 | 70 | var middle = (this.GetPrice(PriceType.High) + this.GetPrice(PriceType.Low)) / 2; 71 | this.down = middle + (this.Digit * this.atrIndicator.GetValue()); 72 | this.up = middle - (this.Digit * this.atrIndicator.GetValue()); 73 | 74 | if (this.GetPrice(PriceType.Close) > this.prevUP) 75 | this.currTrend = 1; 76 | else if (this.GetPrice(PriceType.Close) < this.prevDown) 77 | this.currTrend = -1; 78 | else 79 | this.currTrend = this.prevTrend; 80 | 81 | if (this.currTrend > 0 && up < this.prevDown && this.currTrend <= this.prevTrend) 82 | this.up = this.prevDown; 83 | if (this.currTrend < 0 && this.down > this.prevUP && this.currTrend >= this.prevTrend) 84 | this.down = this.prevUP; 85 | 86 | if (this.currTrend == 1) 87 | { 88 | this.SetValue(this.up); 89 | this.LinesSeries[0].SetMarker(0, this.UpTrendColor); 90 | } 91 | else 92 | { 93 | this.SetValue(this.down); 94 | this.LinesSeries[0].SetMarker(0, this.DownTrendColor); 95 | } 96 | } 97 | 98 | protected override void OnClear() 99 | { 100 | base.OnClear(); 101 | if (this.atrIndicator != null) 102 | { 103 | this.RemoveIndicator(this.atrIndicator); 104 | this.atrIndicator.Dispose(); 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /Indicators/IndicatorRegressionLine.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace MovingAverages; 7 | 8 | public sealed class IndicatorRegressionLine : Indicator, IWatchlistIndicator 9 | { 10 | // Displays Input Parameter as input field (or checkbox if value type is bolean). 11 | [InputParameter("Period of Linear Regression", 0, 1, 9999)] 12 | public int Period = 2; 13 | // Displays Input Parameter as dropdown list. 14 | [InputParameter("Sources prices for the regression line", 1, variants: new object[] { 15 | "Close", PriceType.Close, 16 | "Open", PriceType.Open, 17 | "High", PriceType.High, 18 | "Low", PriceType.Low, 19 | "Typical", PriceType.Typical, 20 | "Medium", PriceType.Median, 21 | "Weighted", PriceType.Weighted, 22 | "Volume", PriceType.Volume, 23 | "Open interest", PriceType.OpenInterest 24 | })] 25 | public PriceType SourcePrice = PriceType.Close; 26 | 27 | public int MinHistoryDepths => this.Period; 28 | public override string ShortName => "REGRESSION " + this.Period; 29 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorRegressionLine.cs"; 30 | 31 | private int sumPeriod; 32 | 33 | /// 34 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 35 | /// 36 | public IndicatorRegressionLine() 37 | : base() 38 | { 39 | // Serves for an identification of related indicators with different parameters. 40 | this.Name = "Regression Line"; 41 | this.Description = "Linear regression line used to measure trends"; 42 | 43 | // Defines line on demand with particular parameters. 44 | this.AddLineSeries("Regression Line", Color.Blue, 1, LineStyle.Solid); 45 | this.SeparateWindow = false; 46 | } 47 | /// 48 | /// This function will be called after creating an indicator as well as after its input params reset or chart (symbol or timeframe) updates. 49 | /// 50 | protected override void OnInit() 51 | { 52 | this.sumPeriod = 0; 53 | for (int i = 0; i < this.Period; i++) 54 | this.sumPeriod += i; 55 | } 56 | /// 57 | /// Calculation entry point. This function is called when a price data updates. 58 | /// Will be runing under the HistoricalBar mode during history loading. 59 | /// Under NewTick during realtime. 60 | /// Under NewBar if start of the new bar is required. 61 | /// 62 | /// Provides data of updating reason and incoming price. 63 | protected override void OnUpdate(UpdateArgs args) 64 | { 65 | if (this.Count < this.MinHistoryDepths) 66 | { 67 | double price = this.GetPrice(this.SourcePrice); 68 | this.SetValue(price); 69 | return; 70 | } 71 | double sumPrices = 0.0; // sum of prices 72 | double sumPeriod_Price = 0.0; // sum of period*price 73 | double sumSqr_Price = 0.0; // sum of price sqr 74 | 75 | // Calculation of sum 76 | for (int i = 0; i < this.Period; i++) 77 | { 78 | double price = this.GetPrice(this.SourcePrice, i); 79 | sumPrices += price; 80 | sumPeriod_Price += i * price; 81 | sumSqr_Price += price * price; 82 | } 83 | 84 | // Calculation of coefficients 85 | double p = (this.Period * sumPeriod_Price - this.sumPeriod * sumPrices) / (this.Period * sumSqr_Price - this.sumPeriod * this.sumPeriod); 86 | double b = (sumPrices * sumSqr_Price - this.sumPeriod * sumPeriod_Price) / (this.Period * sumSqr_Price - this.sumPeriod * this.sumPeriod); 87 | 88 | // Setting of current value 89 | this.SetValue(p * this.Period + b); 90 | } 91 | } -------------------------------------------------------------------------------- /Indicators/IndicatorTripleExponentialAverage.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace MovingAverageIndicators; 7 | 8 | public class IndicatorTripleExponentialAverage : Indicator, IWatchlistIndicator 9 | { 10 | #region Parameters 11 | [InputParameter("Period of Exponential Moving Average", 0, 1, 9999, 1, 0)] 12 | public int MaPeriod = 9; 13 | 14 | [InputParameter("Sources prices for EMA", 1, variants: new object[]{ 15 | "Close", PriceType.Close, 16 | "Open", PriceType.Open, 17 | "High", PriceType.High, 18 | "Low", PriceType.Low, 19 | "Typical", PriceType.Typical, 20 | "Medium", PriceType.Median, 21 | "Weighted", PriceType.Weighted, 22 | "Volume", PriceType.Volume, 23 | "Open interest", PriceType.OpenInterest 24 | })] 25 | public PriceType SourcePrice = PriceType.Close; 26 | // 27 | [InputParameter("Calculation type", 10, variants: new object[] 28 | { 29 | "All available data", IndicatorCalculationType.AllAvailableData, 30 | "By period", IndicatorCalculationType.ByPeriod, 31 | })] 32 | public IndicatorCalculationType CalculationType = Indicator.DEFAULT_CALCULATION_TYPE; 33 | 34 | public int MinHistoryDepths => this.MaPeriod * 3; 35 | public override string ShortName => $"TRIX ({this.MaPeriod}: {this.SourcePrice})"; 36 | 37 | private Indicator emaIndicator; 38 | 39 | private HistoricalDataCustom doubleEmaHD; 40 | private Indicator doubleEmaIndicator; 41 | 42 | private HistoricalDataCustom trixEmaHD; 43 | private Indicator trixEma; 44 | 45 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorTripleExponentialAverage.cs"; 46 | 47 | #endregion Parameters 48 | 49 | public IndicatorTripleExponentialAverage() 50 | { 51 | this.Name = "Triple Exponential Average"; 52 | 53 | this.AddLineSeries("TRIX line", Color.Orange, 2, LineStyle.Solid); 54 | this.AddLineLevel(0d, "Zero line", Color.Gray, 1, LineStyle.Dot); 55 | 56 | this.SeparateWindow = true; 57 | } 58 | 59 | protected override void OnInit() 60 | { 61 | base.OnInit(); 62 | 63 | this.emaIndicator = Core.Indicators.BuiltIn.EMA(this.MaPeriod, PriceType.Close, this.CalculationType); 64 | this.AddIndicator(this.emaIndicator); 65 | 66 | this.doubleEmaHD = new HistoricalDataCustom(this); 67 | this.doubleEmaIndicator = Core.Indicators.BuiltIn.EMA(this.MaPeriod, PriceType.Close, this.CalculationType); 68 | this.doubleEmaHD.AddIndicator(this.doubleEmaIndicator); 69 | 70 | this.trixEmaHD = new HistoricalDataCustom(this); 71 | this.trixEma = Core.Indicators.BuiltIn.EMA(this.MaPeriod, PriceType.Close, this.CalculationType); 72 | this.trixEmaHD.AddIndicator(this.trixEma); 73 | } 74 | protected override void OnUpdate(UpdateArgs args) 75 | { 76 | base.OnUpdate(args); 77 | 78 | if (this.Count < this.MaPeriod) 79 | return; 80 | 81 | this.doubleEmaHD[PriceType.Close] = this.emaIndicator.GetValue(); 82 | 83 | if (this.Count < this.MaPeriod * 2) 84 | return; 85 | 86 | this.trixEmaHD[PriceType.Close] = this.doubleEmaIndicator.GetValue(); 87 | 88 | if (this.Count < this.MinHistoryDepths) 89 | return; 90 | 91 | var trix = (this.trixEma.GetValue() - this.trixEma.GetValue(1)) / this.trixEma.GetValue(1); 92 | this.SetValue(trix); 93 | } 94 | protected override void OnClear() 95 | { 96 | base.OnClear(); 97 | 98 | this.emaIndicator?.Dispose(); 99 | this.doubleEmaIndicator?.Dispose(); 100 | this.trixEma?.Dispose(); 101 | 102 | this.doubleEmaHD?.Dispose(); 103 | this.trixEmaHD?.Dispose(); 104 | } 105 | } -------------------------------------------------------------------------------- /Indicators/IndicatorPriceChannel.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace Channels; 7 | 8 | public sealed class IndicatorPriceChannel : Indicator, IWatchlistIndicator 9 | { 10 | // Define 'Period' input parameter and set allowable range (from 1 to 999) 11 | [InputParameter("Period of price channel", 0, 1, 999)] 12 | public int Period = 20; 13 | 14 | public int MinHistoryDepths => this.Period; 15 | public override string ShortName => $"Channel ({this.Period})"; 16 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorPriceChannel.cs"; 17 | 18 | /// 19 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 20 | /// 21 | public IndicatorPriceChannel() 22 | : base() 23 | { 24 | // Defines indicator's name and description. 25 | this.Name = "Price Channel"; 26 | this.Description = "Based on measurement of min and max prices for the definite number of periods"; 27 | 28 | // Define two lines (on main window) with particular parameters 29 | this.AddLineSeries("Highest", Color.Red, 2, LineStyle.Solid); 30 | this.AddLineSeries("Lowest", Color.CadetBlue, 2, LineStyle.Solid); 31 | 32 | this.SeparateWindow = false; 33 | } 34 | 35 | /// 36 | /// Calculation entry point. This function is called when a price data updates. 37 | /// Will be runing under the HistoricalBar mode during history loading. 38 | /// Under NewTick during realtime. 39 | /// Under NewBar if start of the new bar is required. 40 | /// 41 | /// Provides data of updating reason and incoming price. 42 | protected override void OnUpdate(UpdateArgs args) 43 | { 44 | // Skip some period for correct calculation. 45 | if (this.Count < this.MinHistoryDepths) 46 | return; 47 | 48 | // Get the highest price on the interval 49 | int highestOffset = this.Highest(PriceType.High, 0, this.Period); 50 | double highestPrice = this.GetPrice(PriceType.High, highestOffset); 51 | 52 | // Get the lowest price on the interval 53 | int lowestOffset = this.Lowest(PriceType.Low, 0, this.Period); 54 | double lowestPrice = this.GetPrice(PriceType.Low, lowestOffset); 55 | 56 | // Set highestPrice to 'Highest' line buffer and lowestPrice to 'Lowest' line buffer. 57 | this.SetValue(highestPrice, 0); 58 | this.SetValue(lowestPrice, 1); 59 | } 60 | 61 | /// 62 | ///Get the highest price on an interval. 63 | /// 64 | ///Type of price 65 | ///Start position offset 66 | ///The count of bars in an interval 67 | /// 68 | private int Highest(PriceType priceType, int startOffset, int count) 69 | { 70 | int maxValueOffset = startOffset; 71 | for (int i = 0; i < count; i++) 72 | { 73 | if (this.GetPrice(priceType, maxValueOffset) < this.GetPrice(priceType, startOffset + i)) 74 | maxValueOffset = startOffset + i; 75 | } 76 | return maxValueOffset; 77 | } 78 | 79 | /// 80 | ///Get the lowest price on an interval. 81 | /// 82 | ///Type of price 83 | ///Start position offset 84 | ///The count of bars in an interval 85 | /// 86 | private int Lowest(PriceType priceType, int startOffset, int count) 87 | { 88 | int minValueOffset = startOffset; 89 | for (int i = 0; i < count; i++) 90 | { 91 | if (this.GetPrice(priceType, minValueOffset) > this.GetPrice(priceType, startOffset + i)) 92 | minValueOffset = startOffset + i; 93 | } 94 | return minValueOffset; 95 | } 96 | } -------------------------------------------------------------------------------- /Indicators/IndicatorStochasticRelativeStrengthIndex.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System; 4 | using System.Drawing; 5 | using TradingPlatform.BusinessLayer; 6 | 7 | namespace Oscillators; 8 | 9 | public sealed class IndicatorStochasticRelativeStrengthIndex : Indicator, IWatchlistIndicator 10 | { 11 | [InputParameter("RSI Period", 10, 1, 999, 1, 0)] 12 | public int rsiPeriod = 14; 13 | 14 | [InputParameter("Stochastic period", 20, 1, 999, 1, 0)] 15 | public int StochPeriod = 14; 16 | 17 | [InputParameter("%K Period", 30, 1, 999, 1, 0)] 18 | public int kPeriod = 3; 19 | 20 | [InputParameter("%D Period", 40, 1, 999, 1, 0)] 21 | public int dPeriod = 3; 22 | 23 | [InputParameter("Calculation type", 50, variants: new object[] 24 | { 25 | "All available data", IndicatorCalculationType.AllAvailableData, 26 | "By period", IndicatorCalculationType.ByPeriod, 27 | })] 28 | public IndicatorCalculationType CalculationType = Indicator.DEFAULT_CALCULATION_TYPE; 29 | 30 | public int MinHistoryDepths => this.rsiPeriod + Math.Max(this.kPeriod, this.dPeriod); 31 | public override string ShortName => $"StochasticRSI ({this.rsiPeriod}: {this.StochPeriod}: {this.kPeriod}: {this.dPeriod})"; 32 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorStochasticRelativeStrengthIndex.cs"; 33 | 34 | private Indicator rsi; 35 | private Indicator stochRSI; 36 | private HistoricalDataCustom hCustom; 37 | 38 | /// 39 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 40 | /// 41 | public IndicatorStochasticRelativeStrengthIndex() 42 | : base() 43 | { 44 | // Defines indicator's name and description. 45 | this.Name = "Stochastic x Relative Strength Index"; 46 | this.Description = "StochRSI is an oscillator that measures the level of RSI relative to its range"; 47 | 48 | // Defines line on demand with particular parameters. 49 | this.AddLineSeries("StochRSI", Color.CornflowerBlue, 1, LineStyle.Solid); 50 | this.AddLineSeries("Signal", Color.LightSkyBlue, 1, LineStyle.Solid); 51 | this.AddLineLevel(80, "up", Color.Gray, 1, LineStyle.Dot); 52 | this.AddLineLevel(20, "down", Color.Gray, 1, LineStyle.Dot); 53 | 54 | this.SeparateWindow = true; 55 | } 56 | 57 | /// 58 | /// This function will be called after creating an indicator as well as after its input params reset or chart (symbol or timeframe) updates. 59 | /// 60 | protected override void OnInit() 61 | { 62 | // Creates an instance of the custom historical data which will be synchronized with the current indicator instance. 63 | this.hCustom = new HistoricalDataCustom(this); 64 | this.rsi = Core.Indicators.BuiltIn.RSI(this.rsiPeriod, PriceType.Close, RSIMode.Exponential, MaMode.SMA, 5); 65 | this.AddIndicator(this.rsi); 66 | this.stochRSI = Core.Indicators.BuiltIn.Stochastic(this.StochPeriod, this.kPeriod, this.dPeriod, MaMode.SMA, this.CalculationType); 67 | this.hCustom.AddIndicator(this.stochRSI); 68 | } 69 | 70 | /// 71 | /// Calculation entry point. This function is called when a price data updates. 72 | /// Will be runing under the HistoricalBar mode during history loading. 73 | /// Under NewTick during realtime. 74 | /// Under NewBar if start of the new bar is required. 75 | /// 76 | /// Provides data of updating reason and incoming price. 77 | protected override void OnUpdate(UpdateArgs args) 78 | { 79 | if (this.Count < this.rsiPeriod) 80 | return; 81 | 82 | // Populates custom HistoricalData with 1 data layers: 83 | this.hCustom.SetValue(0d, this.rsi.GetValue(), this.rsi.GetValue(), this.rsi.GetValue()); 84 | 85 | if (this.Count < this.MinHistoryDepths) 86 | return; 87 | 88 | this.SetValue(this.stochRSI.GetValue()); 89 | this.SetValue(this.stochRSI.GetValue(0, 1), 1); 90 | } 91 | } -------------------------------------------------------------------------------- /Indicators/IndicatorTimeHistogram.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using TradingPlatform.BusinessLayer; 7 | 8 | namespace VolumeIndicators; 9 | 10 | internal class IndicatorTimeHistogram : Indicator, IVolumeAnalysisIndicator 11 | { 12 | [InputParameter("Data type", variants: new object[] 13 | { 14 | "Trades", VolumeAnalysisField.Trades, 15 | "Buy trades", VolumeAnalysisField.BuyTrades, 16 | "Sell trades", VolumeAnalysisField.SellTrades, 17 | "Volume", VolumeAnalysisField.Volume, 18 | "Buy volume", VolumeAnalysisField.BuyVolume, 19 | "Buy volume, %", VolumeAnalysisField.BuyVolumePercent, 20 | "Sell volume", VolumeAnalysisField.SellVolume, 21 | "Sell volume, %", VolumeAnalysisField.SellVolumePercent, 22 | "Delta", VolumeAnalysisField.Delta, 23 | "Delta, %", VolumeAnalysisField.DeltaPercent, 24 | "Cumulative delta", VolumeAnalysisField.CumulativeDelta, 25 | "Open interest", VolumeAnalysisField.OpenInterest, 26 | "Average size", VolumeAnalysisField.AverageSize, 27 | "Average buy size", VolumeAnalysisField.AverageBuySize, 28 | "Average sell size", VolumeAnalysisField.AverageSellSize, 29 | "Max one trade Vol.", VolumeAnalysisField.MaxOneTradeVolume, 30 | "Max one trade Vol., %", VolumeAnalysisField.MaxOneTradeVolumePercent, 31 | })] 32 | public VolumeAnalysisField FieldType = VolumeAnalysisField.Volume; 33 | 34 | public override string ShortName => $"Time histogram ({this.FieldType})"; 35 | 36 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorTimeHistogram.cs"; 37 | 38 | public IndicatorTimeHistogram() 39 | { 40 | this.Name = "Time histogram"; 41 | 42 | this.AddLineSeries("Histogram", Color.DodgerBlue, 3, LineStyle.Histogramm); 43 | 44 | this.SeparateWindow = true; 45 | } 46 | 47 | protected override void OnUpdate(UpdateArgs args) 48 | { 49 | if (this.HistoricalData.VolumeAnalysisCalculationProgress == null) 50 | return; 51 | 52 | if (this.HistoricalData.VolumeAnalysisCalculationProgress.State != VolumeAnalysisCalculationState.Finished) 53 | return; 54 | 55 | this.DrawIndicatorValue(); 56 | } 57 | 58 | #region IVolumeAnalysisIndicator 59 | 60 | public bool IsRequirePriceLevelsCalculation => false; 61 | 62 | public void VolumeAnalysisData_Loaded() 63 | { 64 | Task.Factory.StartNew(() => 65 | { 66 | // wait (треба дочекатись поки індикатор пройде всю історію) 67 | while (this.Count != this.HistoricalData.Count) 68 | Thread.Sleep(20); 69 | 70 | // draw history 71 | for (int offset = 0; offset < this.Count; offset++) 72 | this.DrawIndicatorValue(offset); 73 | }); 74 | } 75 | 76 | #endregion IVolumeAnalysisIndicator 77 | 78 | private void DrawIndicatorValue(int offset = 0) 79 | { 80 | if (this.GetVolumeAnalysisData(offset) is VolumeAnalysisData analysisData) 81 | { 82 | double value = analysisData.Total.GetValue(this.FieldType); 83 | this.SetValue(value, 0, offset); 84 | 85 | // Coloring 86 | if (this.IsDeltaBased(this.FieldType)) 87 | { 88 | int markerOffset = offset + 1; 89 | 90 | if (this.Count <= markerOffset) 91 | return; 92 | 93 | if (value > 0) 94 | this.LinesSeries[0].SetMarker(markerOffset, Color.Green); 95 | else if (value < 0) 96 | this.LinesSeries[0].SetMarker(markerOffset, Color.Red); 97 | } 98 | } 99 | } 100 | 101 | private bool IsDeltaBased(VolumeAnalysisField fieldType) => fieldType == VolumeAnalysisField.Delta || fieldType == VolumeAnalysisField.DeltaPercent || fieldType == VolumeAnalysisField.CumulativeDelta; 102 | } -------------------------------------------------------------------------------- /Indicators/IndicatorAverageTrueRange.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | using VolatilityIndicators; 6 | 7 | namespace Volatility; 8 | 9 | public sealed class IndicatorAverageTrueRange : Indicator, IWatchlistIndicator 10 | { 11 | // Displays Input Parameter as input field. 12 | [InputParameter("Period of Moving Average", 0, 1, 999, 1, 0)] 13 | public int Period = 13; 14 | 15 | // Displays Input Parameter as dropdown list. 16 | [InputParameter("Type of Moving Average", 1, variants: new object[] { 17 | "Simple", MaMode.SMA, 18 | "Exponential", MaMode.EMA, 19 | "Smoothed", MaMode.SMMA, 20 | "Linear Weighted", MaMode.LWMA} 21 | )] 22 | public MaMode MAType = MaMode.SMA; 23 | // 24 | [InputParameter("Calculation type", 5, variants: new object[] 25 | { 26 | "All available data", IndicatorCalculationType.AllAvailableData, 27 | "By period", IndicatorCalculationType.ByPeriod, 28 | })] 29 | public IndicatorCalculationType CalculationType = Indicator.DEFAULT_CALCULATION_TYPE; 30 | 31 | public int MinHistoryDepths => this.Period; 32 | public override string ShortName => $"ATR ({this.Period}: {this.MAType})"; 33 | public override string HelpLink => "https://help.quantower.com/analytics-panels/chart/technical-indicators/volatility/average-true-range"; 34 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorAverageTrueRange.cs"; 35 | 36 | private Indicator ma; 37 | private IndicatorTrueRange tr; 38 | private HistoricalDataCustom customHD; 39 | 40 | /// 41 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 42 | /// 43 | public IndicatorAverageTrueRange() 44 | : base() 45 | { 46 | // Defines indicator's name and description. 47 | this.Name = "Average True Range"; 48 | this.Description = "Measures of market volatility."; 49 | this.IsUpdateTypesSupported = false; 50 | 51 | // Defines line on demand with particular parameters. 52 | this.AddLineSeries("ATR", Color.CadetBlue, 1, LineStyle.Solid); 53 | 54 | this.SeparateWindow = true; 55 | } 56 | 57 | /// 58 | /// This function will be called after creating an indicator as well as after its input params reset or chart (symbol or timeframe) updates. 59 | /// 60 | protected override void OnInit() 61 | { 62 | // Get MA indicator from built-in indicator collection (according to selected 'MaType'). 63 | this.ma = Core.Indicators.BuiltIn.MA(this.Period, PriceType.Close, this.MAType, this.CalculationType); 64 | this.ma.UpdateType = IndicatorUpdateType.OnTick; 65 | this.AddIndicator(this.tr = new IndicatorTrueRange() { UpdateType = IndicatorUpdateType.OnTick }); 66 | 67 | // Create a custom HistoricalData and syncronize it with this(ART) indicator. 68 | this.customHD = new HistoricalDataCustom(this); 69 | 70 | // Attach SMA indicator to custom HistoricalData. The MA will calculate on the data, which will store in custom HD. 71 | this.customHD.AddIndicator(this.ma); 72 | } 73 | 74 | /// 75 | /// Calculation entry point. This function is called when a price data updates. 76 | /// Will be runing under the HistoricalBar mode during history loading. 77 | /// Under NewTick during realtime. 78 | /// Under NewBar if start of the new bar is required. 79 | /// 80 | /// Provides data of updating reason and incoming price. 81 | protected override void OnUpdate(UpdateArgs args) 82 | { 83 | // Get the TR value and store it to the custom HistoricalData. 84 | double tr = this.tr.GetValue(); 85 | 86 | this.customHD[PriceType.Close, 0] = tr; 87 | 88 | // Skip some period for correct calculation. 89 | if (this.Count < this.MinHistoryDepths) 90 | return; 91 | 92 | // Get MA value and set it to 'ATR' line buffer. 93 | double maValue = this.ma.GetValue(); 94 | this.SetValue(maValue); 95 | } 96 | } -------------------------------------------------------------------------------- /Indicators/IndicatorContador.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace VolumeIndicators; 7 | 8 | public class IndicatorContador : Indicator 9 | { 10 | // consts 11 | public const string ERROR_MESSAGE = "Tick Counter only works on bars build with a set number of ticks"; 12 | public const string TICKS_REMAINING_PREFIX = "Ticks Remaining = "; 13 | public const string TICK_COUNTER_PREFIX = "Ticks Count = "; 14 | public const string COUNTDOWN = "Countdown"; 15 | public const string SHOW_PERCENTAGES = "Show percentages"; 16 | 17 | // input parameters 18 | [InputParameter(COUNTDOWN, 10)] 19 | public bool IsCountdown = true; 20 | [InputParameter(SHOW_PERCENTAGES, 10)] 21 | public bool ShowPercentages = true; 22 | [InputParameter("Font color", 20)] 23 | public Color FontColor 24 | { 25 | get => this.fontColor; 26 | set 27 | { 28 | this.fontColor = value; 29 | this.fontBrush = new SolidBrush(value); 30 | } 31 | } 32 | private Color fontColor; 33 | private SolidBrush fontBrush; 34 | 35 | public override string ShortName 36 | { 37 | get 38 | { 39 | string parameters = this.IsCountdown ? COUNTDOWN : string.Empty; 40 | 41 | if (this.ShowPercentages) 42 | { 43 | if (this.IsCountdown) 44 | parameters += ": "; 45 | 46 | parameters += SHOW_PERCENTAGES; 47 | } 48 | 49 | return $"{this.Name} ({parameters})"; 50 | } 51 | } 52 | 53 | private readonly Font font; 54 | private bool isCorrectTimeFrame = false; 55 | private string calculatedMessage; 56 | private int messageMargin = 0; 57 | private string prefix; 58 | private readonly StringFormat farFarSF; 59 | 60 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorContador.cs"; 61 | 62 | public IndicatorContador() 63 | { 64 | this.Name = "Contador"; 65 | this.font = new Font("Verdana", 10, FontStyle.Regular, GraphicsUnit.Point); 66 | this.FontColor = Color.Orange; 67 | this.farFarSF = new StringFormat() 68 | { 69 | Alignment = StringAlignment.Far, 70 | LineAlignment = StringAlignment.Far 71 | }; 72 | } 73 | 74 | protected override void OnInit() 75 | { 76 | this.calculatedMessage = string.Empty; 77 | this.isCorrectTimeFrame = this.HistoricalData.Aggregation.GetPeriod.BasePeriod == BasePeriod.Tick; 78 | this.messageMargin = this.isCorrectTimeFrame 79 | ? 30 80 | : 70; 81 | 82 | this.prefix = this.IsCountdown 83 | ? TICKS_REMAINING_PREFIX 84 | : TICK_COUNTER_PREFIX; 85 | } 86 | protected override void OnUpdate(UpdateArgs args) 87 | { 88 | if (args.Reason == UpdateReason.Unknown || args.Reason == UpdateReason.HistoricalBar) 89 | return; 90 | 91 | if (this.isCorrectTimeFrame) 92 | { 93 | int ticksCount = this.IsCountdown 94 | ? this.HistoricalData.Aggregation.GetPeriod.PeriodMultiplier - (int)this.Ticks() 95 | : (int)this.Ticks(); 96 | 97 | this.calculatedMessage = this.ShowPercentages 98 | ? this.prefix + ticksCount * 100 / this.HistoricalData.Aggregation.GetPeriod.PeriodMultiplier + " %" 99 | : this.prefix + ticksCount.ToString(); 100 | } 101 | } 102 | public override void OnPaintChart(PaintChartEventArgs args) 103 | { 104 | var gr = args.Graphics; 105 | 106 | string message = this.isCorrectTimeFrame ? this.calculatedMessage : ERROR_MESSAGE; 107 | 108 | gr.DrawString(message, this.font, this.fontBrush, args.Rectangle.Width - this.messageMargin, args.Rectangle.Height - 2, this.farFarSF); 109 | } 110 | public override void Dispose() 111 | { 112 | this.font?.Dispose(); 113 | this.fontBrush?.Dispose(); 114 | this.farFarSF?.Dispose(); 115 | } 116 | } -------------------------------------------------------------------------------- /Indicators/IndicatorMcGinleyDynamic.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System; 4 | using System.Drawing; 5 | using TradingPlatform.BusinessLayer; 6 | 7 | namespace MovingAverages; 8 | 9 | /// 10 | /// McGinley Dynamic avoids of most whipsaws and it rapidly moves up or down according to a quickly changing market. It needs no adjusting because it is dynamic and it adjusts itself. 11 | /// 12 | public sealed class IndicatorMcGinleyDynamic : Indicator, IWatchlistIndicator 13 | { 14 | // Period of McGinley Dynamic. 15 | [InputParameter("Period", 0, 2, 999, 1, 0)] 16 | public int Period = 14; 17 | 18 | // Dynamic tracking factor of McGinley Dynamic. 19 | [InputParameter("Dynamic tracking factor", 1, 1, 999, 1, 0)] 20 | public int TrackingFactor = 2; 21 | 22 | // Price type of McGinley Dynamic. 23 | [InputParameter("Source price", 2, variants: new object[] 24 | { 25 | "Close", PriceType.Close, 26 | "Open", PriceType.Open, 27 | "High", PriceType.High, 28 | "Low", PriceType.Low, 29 | "Typical", PriceType.Typical, 30 | "Median", PriceType.Median, 31 | "Weighted", PriceType.Weighted, 32 | "Volume", PriceType.Volume, 33 | "Open interest", PriceType.OpenInterest 34 | })] 35 | public PriceType SourcePrice = PriceType.Close; 36 | 37 | [InputParameter("Calculation type", 5, variants: new object[] 38 | { 39 | "All available data", IndicatorCalculationType.AllAvailableData, 40 | "By period", IndicatorCalculationType.ByPeriod, 41 | })] 42 | public IndicatorCalculationType CalculationType = Indicator.DEFAULT_CALCULATION_TYPE; 43 | 44 | public int MinHistoryDepths => this.Period + 1; 45 | public override string ShortName => $"MD ({this.Period}: {this.TrackingFactor}: {this.SourcePrice})"; 46 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorMcGinleyDynamic.cs"; 47 | 48 | // Holds EMA's smoothing values. 49 | private Indicator ema; 50 | 51 | /// 52 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 53 | /// 54 | public IndicatorMcGinleyDynamic() 55 | : base() 56 | { 57 | // Defines indicator's group, name and description. 58 | this.Name = "McGinley Dynamic"; 59 | this.Description = "McGinley Dynamic avoids of most whipsaws and it rapidly moves up or down according to a quickly changing market. It needs no adjusting because it is dynamic and it adjusts itself."; 60 | 61 | // Defines line on demand with particular parameters. 62 | this.AddLineSeries("MD", Color.DodgerBlue, 1, LineStyle.Solid); 63 | } 64 | 65 | /// 66 | /// This function will be called after creating an indicator as well as after its input params reset or chart (symbol or timeframe) updates. 67 | /// 68 | protected override void OnInit() 69 | { 70 | // Creates an instance of the proper indicator from the default indicators list. 71 | this.ema = Core.Indicators.BuiltIn.EMA(this.Period, this.SourcePrice, this.CalculationType); 72 | // Adds an auxiliary (MA) indicator to the current one (MD). 73 | // This will let inner indicator (MA) to be calculated in advance to the current one (MD). 74 | this.AddIndicator(this.ema); 75 | } 76 | 77 | /// 78 | /// Calculation entry point. This function is called when a price data updates. 79 | /// Will be runing under the HistoricalBar mode during history loading. 80 | /// Under NewTick during realtime. 81 | /// Under NewBar if start of the new bar is required. 82 | /// 83 | /// Provides data of updating reason and incoming price. 84 | protected override void OnUpdate(UpdateArgs args) 85 | { 86 | // Checking, if current amount of bars less, than period of moving average (+ 1) - calculation is impossible. 87 | if (this.Count < this.MinHistoryDepths) 88 | return; 89 | 90 | // Gets calculated value. 91 | double md = this.GetPrice(this.SourcePrice); 92 | double value = this.ema.GetValue(1); 93 | md = value + (md - value) / (this.TrackingFactor * Math.Pow(md / value, 4)); 94 | 95 | // Sets value for displaying on the chart. 96 | this.SetValue(md); 97 | } 98 | } -------------------------------------------------------------------------------- /Indicators/IndicatorStandardDeviation.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System; 4 | using System.Drawing; 5 | using TradingPlatform.BusinessLayer; 6 | 7 | namespace Volatility; 8 | 9 | /// 10 | /// Shows the difference of the volatility value from the average one. 11 | /// 12 | public sealed class IndicatorStandardDeviation : Indicator, IWatchlistIndicator 13 | { 14 | public override string HelpLink => "https://help.quantower.com/analytics-panels/chart/technical-indicators/volatility/standard-deviation"; 15 | 16 | // Displays Input Parameter as dropdown list. 17 | [InputParameter("Sources prices for MA", 0, variants: new object[] { 18 | "Close", PriceType.Close, 19 | "Open", PriceType.Open, 20 | "High", PriceType.High, 21 | "Low", PriceType.Low, 22 | "Typical", PriceType.Typical, 23 | "Medium", PriceType.Median, 24 | "Weighted", PriceType.Weighted, 25 | "Volume", PriceType.Volume, 26 | "Open interest", PriceType.OpenInterest 27 | })] 28 | public PriceType SourcePrice = PriceType.Close; 29 | 30 | [InputParameter("Type of Moving Average", 1, variants: new object[] { 31 | "Simple", MaMode.SMA, 32 | "Exponential", MaMode.EMA, 33 | "Modified", MaMode.SMMA, 34 | "Linear Weighted", MaMode.LWMA} 35 | )] 36 | public MaMode MAType = MaMode.SMA; 37 | // 38 | [InputParameter("Calculation type", 5, variants: new object[] 39 | { 40 | "All available data", IndicatorCalculationType.AllAvailableData, 41 | "By period", IndicatorCalculationType.ByPeriod, 42 | })] 43 | public IndicatorCalculationType CalculationType = Indicator.DEFAULT_CALCULATION_TYPE; 44 | 45 | // Displays Input Parameter as input field (or checkbox if value type is boolean). 46 | [InputParameter("Period", 10, 1, 999, 1, 0)] 47 | public int Period = 20; 48 | 49 | public int MinHistoryDepths => this.Period; 50 | public override string ShortName => $"SD ({this.Period}: {this.SourcePrice}: {this.MAType})"; 51 | 52 | // Holds moving average values. 53 | private Indicator ma; 54 | 55 | /// 56 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 57 | /// 58 | public IndicatorStandardDeviation() 59 | : base() 60 | { 61 | // Defines indicator's group, name and description. 62 | this.Name = "Standard Deviation"; 63 | this.Description = "Shows the difference of the volatility value from the average one."; 64 | 65 | // Defines line on demand with particular parameters. 66 | this.AddLineSeries("SD'Line", Color.Blue, 1, LineStyle.Solid); 67 | 68 | this.SeparateWindow = true; 69 | } 70 | 71 | /// 72 | /// This function will be called after creating an indicator as well as after its input params reset or chart (symbol or timeframe) updates. 73 | /// 74 | protected override void OnInit() 75 | { 76 | // Creates an instance of the proper indicator from the default indicators list. 77 | this.ma = Core.Indicators.BuiltIn.MA(this.Period, this.SourcePrice, this.MAType, this.CalculationType); 78 | // Adds an auxiliary (MA) indicator to the current one (SD). 79 | // This will let inner indicator (MA) to be calculated in advance to the current one (SD). 80 | this.AddIndicator(this.ma); 81 | } 82 | 83 | /// 84 | /// Calculation entry point. This function is called when a price data updates. 85 | /// Will be runing under the HistoricalBar mode during history loading. 86 | /// Under NewTick during realtime. 87 | /// Under NewBar if start of the new bar is required. 88 | /// 89 | /// Provides data of updating reason and incoming price. 90 | protected override void OnUpdate(UpdateArgs args) 91 | { 92 | // Skip if count is smaller than period value. 93 | if (this.Count < this.MinHistoryDepths) 94 | return; 95 | 96 | // Processes calculating loop. 97 | double dAmount = 0; 98 | double movingAverage = this.ma.GetValue(); 99 | for (int j = 0; j < this.Period; j++) 100 | dAmount += Math.Pow(this.GetPrice(this.SourcePrice, j) - movingAverage, 2); 101 | 102 | this.SetValue(Math.Sqrt(dAmount / this.Period)); 103 | } 104 | } -------------------------------------------------------------------------------- /Indicators/IndicatorAccelerationOscillator.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace Oscillators; 7 | 8 | /// 9 | /// Acceleration/Deceleration Oscillator measures the acceleration and deceleration of the current momentum. 10 | /// 11 | public sealed class IndicatorAccelerationOscillator : Indicator, IWatchlistIndicator 12 | { 13 | private const int AC_PERIOD = 5; 14 | private const int AO_MAX_PERIOD = 34; 15 | 16 | public override string HelpLink => "https://help.quantower.com/analytics-panels/chart/technical-indicators/oscillators/accelerator-oscillator"; 17 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorAccelerationOscillator.cs"; 18 | public int MinHistoryDepths => AC_PERIOD + AO_MAX_PERIOD; 19 | public override string ShortName => "AC"; 20 | 21 | // Custom historical data to keep calculated values SMA(AO, 5). 22 | private HistoricalDataCustom customHistData; 23 | // Calculation indicators. 24 | private Indicator ao; 25 | private Indicator smaAO; 26 | 27 | /// 28 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 29 | /// 30 | public IndicatorAccelerationOscillator() 31 | : base() 32 | { 33 | // Defines indicator's group, name and description. 34 | this.Name = "Acceleration Oscillator"; 35 | this.Description = "Acceleration/Deceleration Oscillator (AC) measures the acceleration and deceleration of the current momentum."; 36 | 37 | // Defines line on demand with particular parameters. 38 | this.AddLineSeries("AC'Line", Color.Gray, 2, LineStyle.Histogramm); 39 | this.SeparateWindow = true; 40 | } 41 | 42 | /// 43 | /// This function will be called after creating an indicator as well as after its input params reset or chart (symbol or timeframe) updates. 44 | /// 45 | protected override void OnInit() 46 | { 47 | // Creates an instance of the custom historical data which will be syncronized by the current indicator instance. 48 | this.customHistData = new HistoricalDataCustom(this); 49 | 50 | // Creates a smoothing indicator which will keep smoothed custom data (for close prices). 51 | this.smaAO = Core.Indicators.BuiltIn.SMA(AC_PERIOD, PriceType.Close); 52 | 53 | // Adds the smoothing indicator to the custom historical data. 54 | this.customHistData.AddIndicator(this.smaAO); 55 | 56 | // Creates auxiliary indicator to calculate AO value with current historical data. 57 | this.ao = Core.Indicators.BuiltIn.AO(); 58 | this.AddIndicator(this.ao); 59 | } 60 | 61 | /// 62 | /// Calculation entry point. This function is called when a price data updates. 63 | /// Will be runing under the HistoricalBar mode during history loading. 64 | /// Under NewTick during realtime. 65 | /// Under NewBar if start of the new bar is required. 66 | /// 67 | /// Provides data of updating reason and incoming price. 68 | protected override void OnUpdate(UpdateArgs args) 69 | { 70 | if (this.Count < AO_MAX_PERIOD) 71 | return; 72 | 73 | // Gets AO indicator value. 74 | double aoValue = this.ao.GetValue(); 75 | 76 | // The calculated value must be set as close price against the custom HistoricalData (a respective price type argument), 77 | // because the SMA indicator was initialized with the source price - PriceType.Close. 78 | this.customHistData.SetValue(0, 0, 0, aoValue); 79 | 80 | if (this.Count < this.MinHistoryDepths) 81 | return; 82 | 83 | // Calculates difference between AO's value and smoothed custom historical data: AC = AO - SMA(AO,5). 84 | double differ = aoValue - this.smaAO.GetValue(); 85 | 86 | // Skips value setting if it's NaN. 87 | if (double.IsNaN(differ)) 88 | return; 89 | 90 | double prevDiffer = (this.Count > 1) ? this.GetValue(1) : differ; 91 | 92 | // Sets value for displaying on the chart. 93 | this.SetValue(aoValue - this.smaAO.GetValue()); 94 | 95 | if (prevDiffer < differ) 96 | this.LinesSeries[0].SetMarker(0, Color.Green); 97 | else if (prevDiffer > differ) 98 | this.LinesSeries[0].SetMarker(0, Color.Red); 99 | } 100 | } -------------------------------------------------------------------------------- /Indicators/IndicatorRelativeStrengthIndexSmoothed.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace OscillatorsIndicators; 7 | 8 | public class IndicatorRelativeStrengthIndexSmoothed : Indicator, IWatchlistIndicator 9 | { 10 | #region Parameters 11 | [InputParameter("RSI period", 10, 1, 9999, 1, 0)] 12 | public int Period = 14; 13 | 14 | [InputParameter("Sources prices", 20, variants: new object[] { 15 | "Close", PriceType.Close, 16 | "Open", PriceType.Open, 17 | "High", PriceType.High, 18 | "Low", PriceType.Low, 19 | "Typical", PriceType.Typical, 20 | "Medium", PriceType.Median, 21 | "Weighted", PriceType.Weighted, 22 | "Volume", PriceType.Volume, 23 | "Open interest", PriceType.OpenInterest 24 | })] 25 | public PriceType SourcePrice = PriceType.Close; 26 | 27 | [InputParameter("Smooth period", 30, 1, 9999, 1, 0)] 28 | public int SmoothPeriod = 5; 29 | 30 | [InputParameter("Type of Moving Average", 40, variants: new object[] { 31 | "Simple", MaMode.SMA, 32 | "Exponential", MaMode.EMA, 33 | "Smoothed Modified", MaMode.SMMA, 34 | "Linear Weighted", MaMode.LWMA} 35 | )] 36 | public MaMode MaType = MaMode.SMA; 37 | 38 | [InputParameter("MA period", 50, 1, 9999, 1, 0)] 39 | public int MAPeriod = 9; 40 | 41 | [InputParameter("Calculation type", 60, variants: new object[] 42 | { 43 | "All available data", IndicatorCalculationType.AllAvailableData, 44 | "By period", IndicatorCalculationType.ByPeriod, 45 | })] 46 | public IndicatorCalculationType CalculationType = Indicator.DEFAULT_CALCULATION_TYPE; 47 | private Indicator ema; 48 | private HistoricalDataCustom customHD; 49 | private Indicator rsi; 50 | 51 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorRelativeStrengthIndexSmoothed.cs"; 52 | 53 | #endregion Parameters 54 | 55 | #region IWatchlistIndicator 56 | public int MinHistoryDepths 57 | { 58 | get 59 | { 60 | var rsiPeriod = this.Period + this.MAPeriod; 61 | 62 | if (this.CalculationType == IndicatorCalculationType.ByPeriod) 63 | rsiPeriod *= 2; 64 | 65 | return EmaPeriod + rsiPeriod; 66 | } 67 | } 68 | private int EmaPeriod => this.CalculationType == IndicatorCalculationType.ByPeriod ? this.SmoothPeriod : this.SmoothPeriod * 2; 69 | #endregion IWatchlistIndicator 70 | 71 | public IndicatorRelativeStrengthIndexSmoothed() 72 | { 73 | this.Name = "RSI Smoothed"; 74 | 75 | this.AddLineSeries("RSI Smoothed", Color.DodgerBlue, 2, LineStyle.Solid); 76 | this.AddLineSeries("RSI Average", Color.Orange, 1, LineStyle.Solid); 77 | 78 | this.AddLineLevel(70d, "Up level", Color.Gray, 1, LineStyle.Dash); 79 | this.AddLineLevel(30d, "Down level", Color.Gray, 1, LineStyle.Dash); 80 | this.AddLineLevel(50d, "Middle level", Color.Gray, 1, LineStyle.Dash); 81 | 82 | this.SeparateWindow = true; 83 | } 84 | 85 | protected override void OnInit() 86 | { 87 | this.ema = Core.Instance.Indicators.BuiltIn.EMA(this.SmoothPeriod, this.SourcePrice, this.CalculationType); 88 | this.AddIndicator(this.ema); 89 | 90 | this.customHD = new HistoricalDataCustom(); 91 | this.rsi = Core.Instance.Indicators.BuiltIn.RSI(this.Period, this.SourcePrice, RSIMode.Exponential, this.MaType, this.MAPeriod, this.CalculationType); 92 | this.customHD.AddIndicator(this.rsi); 93 | } 94 | protected override void OnUpdate(UpdateArgs args) 95 | { 96 | if (this.Count <= this.EmaPeriod) 97 | return; 98 | 99 | var emaValue = this.ema.GetValue(); 100 | 101 | if (args.Reason != UpdateReason.NewTick) 102 | this.customHD.AddValue(emaValue, emaValue, emaValue, emaValue); 103 | else 104 | this.customHD.SetValue(emaValue, emaValue, emaValue, emaValue); 105 | 106 | if (this.Count < this.MinHistoryDepths) 107 | return; 108 | 109 | SetValue(this.rsi.GetValue(), 0); 110 | SetValue(this.rsi.GetValue(0, 1), 1); 111 | } 112 | protected override void OnClear() 113 | { 114 | this.RemoveIndicator(this.ema); 115 | this.ema?.Dispose(); 116 | 117 | this.customHD.RemoveIndicator(this.rsi); 118 | this.rsi?.Dispose(); 119 | this.customHD?.Dispose(); 120 | } 121 | } -------------------------------------------------------------------------------- /Indicators/IndicatorPriceOscillator.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using System.Linq; 5 | using TradingPlatform.BusinessLayer; 6 | 7 | namespace Oscillators; 8 | 9 | /// 10 | /// Calculates the variation between price moving averages. 11 | /// 12 | public sealed class IndicatorPriceOscillator : Indicator, IWatchlistIndicator 13 | { 14 | // Displays Input Parameter as dropdown list. 15 | [InputParameter("Type of Moving Average", 0, variants: new object[] { 16 | "Simple", MaMode.SMA, 17 | "Exponential", MaMode.EMA, 18 | "Modified", MaMode.SMMA, 19 | "Linear Weighted", MaMode.LWMA} 20 | )] 21 | public MaMode MAType = MaMode.SMA; 22 | // 23 | [InputParameter("Calculation type", 1, variants: new object[] 24 | { 25 | "All available data", IndicatorCalculationType.AllAvailableData, 26 | "By period", IndicatorCalculationType.ByPeriod, 27 | })] 28 | public IndicatorCalculationType CalculationType = Indicator.DEFAULT_CALCULATION_TYPE; 29 | 30 | 31 | [InputParameter("Sources prices for MA", 2, variants: new object[] { 32 | "Close", PriceType.Close, 33 | "Open", PriceType.Open, 34 | "High", PriceType.High, 35 | "Low", PriceType.Low, 36 | "Typical", PriceType.Typical, 37 | "Medium", PriceType.Median, 38 | "Weighted", PriceType.Weighted, 39 | "Volume", PriceType.Volume, 40 | "Open interest", PriceType.OpenInterest 41 | })] 42 | public PriceType SourcePrice = PriceType.Close; 43 | 44 | // Displays Input Parameter as input field (or checkbox if value type is bolean). 45 | [InputParameter("Period of MA1", 3, 1, 999, 1, 0)] 46 | public int MAPeriod1 = 10; 47 | 48 | [InputParameter("Period of MA2", 4, 1, 999, 1, 0)] 49 | public int MAPeriod2 = 21; 50 | 51 | public int MinHistoryDepths => Enumerable.Max(new int[] { this.MAPeriod1, this.MAPeriod2 }); 52 | public override string ShortName => $"PO ({this.MAPeriod1}: {this.MAPeriod2}: {this.SourcePrice}: {this.MAType})"; 53 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorPriceOscillator.cs"; 54 | 55 | // Holds moving averages values. 56 | private Indicator ma1, ma2; 57 | 58 | /// 59 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 60 | /// 61 | public IndicatorPriceOscillator() 62 | : base() 63 | { 64 | // Defines indicator's group, name and description. 65 | this.Name = "Price Oscillator"; 66 | this.Description = "Calculates the variation between price moving averages."; 67 | 68 | // Defines line and level with particular parameters. 69 | this.AddLineSeries("PO'Line", Color.Blue, 1, LineStyle.Solid); 70 | this.AddLineLevel(0, "0'Line", Color.Gray, 1, LineStyle.Solid); 71 | this.SeparateWindow = true; 72 | } 73 | 74 | /// 75 | /// This function will be called after creating an indicator as well as after its input params reset or chart (symbol or timeframe) updates. 76 | /// 77 | protected override void OnInit() 78 | { 79 | // Creates an instances of the proper indicators (MA1, MA2) from the default indicators list. 80 | this.ma1 = Core.Indicators.BuiltIn.MA(this.MAPeriod1, this.SourcePrice, this.MAType, this.CalculationType); 81 | this.ma2 = Core.Indicators.BuiltIn.MA(this.MAPeriod2, this.SourcePrice, this.MAType, this.CalculationType); 82 | 83 | // Adds an auxiliary (MA1, MA2) indicator to the current one (PO). 84 | // This will let inner indicator (MA1, MA2) to be calculated in advance to the current one (PO). 85 | this.AddIndicator(this.ma1); 86 | this.AddIndicator(this.ma2); 87 | } 88 | 89 | /// 90 | /// Calculation entry point. This function is called when a price data updates. 91 | /// Will be runing under the HistoricalBar mode during history loading. 92 | /// Under NewTick during realtime. 93 | /// Under NewBar if start of the new bar is required. 94 | /// 95 | /// Provides data of updating reason and incoming price. 96 | protected override void OnUpdate(UpdateArgs args) 97 | { 98 | // Skip if count is smaller than maximal period value. 99 | if (this.Count < this.MinHistoryDepths) 100 | return; 101 | 102 | // Sets value for displaying on the chart. 103 | this.SetValue(this.ma1.GetValue() - this.ma2.GetValue()); 104 | } 105 | } -------------------------------------------------------------------------------- /Indicators/IndicatorSchaffTrendCycle.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace TrendIndicators; 7 | 8 | public class IndicatorSchaffTrendCycle : Indicator 9 | { 10 | [InputParameter("Fast Period", 10, 1, 9999, 1, 0)] 11 | public int fastPeriod; 12 | 13 | [InputParameter("Slow Period", 10, 1, 9999, 1, 0)] 14 | public int slowPeriod; 15 | 16 | [InputParameter("k Period", 10, 1, 9999, 1, 0)] 17 | public int kPeriod; 18 | 19 | [InputParameter("d Period", 10, 1, 9999, 1, 0)] 20 | public int dPeriod; 21 | 22 | [InputParameter("High Line", 10, 0, 100)] 23 | public int HighLine; 24 | 25 | [InputParameter("Low Line", 10, 0, 100)] 26 | public int LowLine; 27 | 28 | [InputParameter("Sources prices for MA", 20, variants: new object[] 29 | { 30 | "Close", PriceType.Close, 31 | "Open", PriceType.Open, 32 | "High", PriceType.High, 33 | "Low", PriceType.Low, 34 | "Typical", PriceType.Typical, 35 | "Medium", PriceType.Median, 36 | "Weighted", PriceType.Weighted, 37 | })] 38 | public PriceType SourcePrice; 39 | 40 | [InputParameter("Smoothing type", 3, variants: new object[]{ 41 | "Simple Moving Average", MaMode.SMA, 42 | "Exponential Moving Average", MaMode.EMA, 43 | "Smoothed Moving Average", MaMode.SMMA, 44 | "Linearly Weighted Moving Average", MaMode.LWMA, 45 | })] 46 | public MaMode MaType; 47 | 48 | private Indicator fastMA; 49 | private Indicator slowMA; 50 | private Indicator stochasticOscillator; 51 | private Indicator stochasticOscillatorPF; 52 | private Indicator stochasticOscillatorPFF; 53 | 54 | private HistoricalDataCustom macd; 55 | private HistoricalDataCustom pf; 56 | private HistoricalDataCustom pff; 57 | 58 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorSchaffTrendCycle.cs"; 59 | public IndicatorSchaffTrendCycle() 60 | : base() 61 | { 62 | this.Name = "Schaff Trend Cycle"; 63 | this.SeparateWindow = true; 64 | 65 | this.MaType = MaMode.SMA; 66 | this.SourcePrice = PriceType.Close; 67 | 68 | this.fastPeriod = 23; 69 | this.slowPeriod = 50; 70 | this.kPeriod = 10; 71 | this.dPeriod = 10; 72 | this.HighLine = 80; 73 | this.LowLine = 20; 74 | 75 | this.AddLineSeries("Main Line", Color.CadetBlue, 1, LineStyle.Solid); 76 | this.AddLineSeries("High Line", Color.Green, 1, LineStyle.Solid); 77 | this.AddLineSeries("Low Line", Color.Red, 1, LineStyle.Solid); 78 | } 79 | 80 | 81 | protected override void OnInit() 82 | { 83 | this.fastMA = Core.Instance.Indicators.BuiltIn.EMA(this.fastPeriod, this.SourcePrice); 84 | this.slowMA = Core.Instance.Indicators.BuiltIn.EMA(this.slowPeriod, this.SourcePrice); 85 | 86 | this.stochasticOscillator = Core.Instance.Indicators.BuiltIn.Stochastic(this.kPeriod, this.dPeriod, this.dPeriod * 2, this.MaType); 87 | this.stochasticOscillatorPF = Core.Instance.Indicators.BuiltIn.Stochastic(this.kPeriod, this.dPeriod, this.dPeriod * 2, this.MaType); 88 | this.stochasticOscillatorPFF = Core.Instance.Indicators.BuiltIn.Stochastic(this.kPeriod, this.dPeriod, this.dPeriod * 2, this.MaType); 89 | 90 | this.macd = new HistoricalDataCustom(this); 91 | this.pf = new HistoricalDataCustom(this); 92 | this.pff = new HistoricalDataCustom(this); 93 | 94 | this.AddIndicator(this.fastMA); 95 | this.AddIndicator(this.slowMA); 96 | 97 | this.macd.AddIndicator(this.stochasticOscillator); 98 | this.pf.AddIndicator(this.stochasticOscillatorPF); 99 | this.pff.AddIndicator(this.stochasticOscillatorPFF); 100 | } 101 | 102 | protected override void OnUpdate(UpdateArgs args) 103 | { 104 | if (this.Count < this.slowPeriod) 105 | return; 106 | 107 | double currentMACD = this.fastMA.GetValue() - this.slowMA.GetValue(); 108 | this.macd.SetValue(currentMACD, currentMACD, currentMACD, currentMACD); 109 | 110 | double d = this.stochasticOscillator.GetValue(0, 1); 111 | this.pf.SetValue(d, d, d, d); 112 | 113 | double pf = this.stochasticOscillatorPF.GetValue(); 114 | this.pff.SetValue(pf, pf, pf, pf); 115 | 116 | double pff = this.stochasticOscillatorPFF.GetValue(0, 1); 117 | this.SetValue(pff); 118 | this.SetValue(this.HighLine, 1); 119 | this.SetValue(this.LowLine, 2); 120 | } 121 | } -------------------------------------------------------------------------------- /Indicators/IndicatorBollingerBands.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System; 4 | using System.Drawing; 5 | using TradingPlatform.BusinessLayer; 6 | 7 | namespace Channels; 8 | 9 | public sealed class IndicatorBollingerBands : Indicator, IWatchlistIndicator 10 | { 11 | //Defines input parameters as input fields 12 | [InputParameter("Period of MA for envelopes", 0, 1, 999)] 13 | public int Period = 20; 14 | [InputParameter("Value of confidence interval", 1, 0.01, 100.0, 0.01, 2)] 15 | public double D = 2.0; 16 | 17 | //Defines input parameters as dropdown lists 18 | [InputParameter("Sources prices for MA", 2, variants: new object[] { 19 | "Close", PriceType.Close, 20 | "Open", PriceType.Open, 21 | "High", PriceType.High, 22 | "Low", PriceType.Low, 23 | "Typical", PriceType.Typical, 24 | "Medium", PriceType.Median, 25 | "Weighted", PriceType.Weighted, 26 | "Volume", PriceType.Volume, 27 | "Open interest", PriceType.OpenInterest 28 | })] 29 | public PriceType SourcePrices = PriceType.Close; 30 | [InputParameter("Type of moving average", 3, variants: new object[]{ 31 | "Simple Moving Average", MaMode.SMA, 32 | "Exponential Moving Average", MaMode.EMA, 33 | "Smoothed Moving Average", MaMode.SMMA, 34 | "Linearly Weighted Moving Average", MaMode.LWMA, 35 | })] 36 | public MaMode MaType = MaMode.SMA; 37 | 38 | [InputParameter("Calculation type", 4, variants: new object[] 39 | { 40 | "All available data", IndicatorCalculationType.AllAvailableData, 41 | "By period", IndicatorCalculationType.ByPeriod, 42 | })] 43 | public IndicatorCalculationType CalculationType = Indicator.DEFAULT_CALCULATION_TYPE; 44 | 45 | public int MinHistoryDepths => this.Period; 46 | public override string ShortName => $"BB ({this.Period}:{this.D})"; 47 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorBollingerBands.cs"; 48 | 49 | private Indicator ma; 50 | 51 | /// 52 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 53 | /// 54 | public IndicatorBollingerBands() 55 | : base() 56 | { 57 | // Defines indicator's name and description. 58 | this.Name = "Bollinger Bands"; 59 | this.Description = "Provides a relative definition of high and low based on standard deviation and a simple moving average"; 60 | 61 | // Defines three lines with particular parameters. 62 | this.AddLineSeries("Upper Band", Color.Red, 2, LineStyle.Solid); 63 | this.AddLineSeries("Middle Band", Color.Gray, 2, LineStyle.Solid); 64 | this.AddLineSeries("Lower Band", Color.Green, 2, LineStyle.Solid); 65 | 66 | this.SeparateWindow = false; 67 | } 68 | 69 | /// 70 | /// This function will be called after creating an indicator as well as after its input params reset or chart (symbol or timeframe) updates. 71 | /// 72 | protected override void OnInit() 73 | { 74 | // Get MA indicator from built-in indicator collection (according to selected 'MaType') 75 | this.ma = Core.Indicators.BuiltIn.MA(this.Period, this.SourcePrices, this.MaType, this.CalculationType); 76 | this.AddIndicator(this.ma); 77 | } 78 | 79 | /// 80 | /// Calculation entry point. This function is called when a price data updates. 81 | /// Will be runing under the HistoricalBar mode during history loading. 82 | /// Under NewTick during realtime. 83 | /// Under NewBar if start of the new bar is required. 84 | /// 85 | /// Provides data of updating reason and incoming price. 86 | protected override void OnUpdate(UpdateArgs args) 87 | { 88 | // Checking, if current amount of bars 89 | // more, than period of moving average. If it is 90 | // then the calculation is possible 91 | if (this.Count < this.MinHistoryDepths) 92 | return; 93 | 94 | // Get MA value of current bar (0 offset by default) 95 | double maValue = this.ma.GetValue(); 96 | 97 | // Calulation of the sum 98 | double sum = 0.0; 99 | for (int i = 0; i < this.Period; i++) 100 | sum += Math.Pow(this.GetPrice(this.SourcePrices, i) - maValue, 2); 101 | 102 | // Calculation of deviation value 103 | sum = this.D * Math.Sqrt(sum / this.Period); 104 | 105 | // set values to line buffers 106 | this.SetValue(maValue + sum); 107 | this.SetValue(maValue, 1); 108 | this.SetValue(maValue - sum, 2); 109 | } 110 | } -------------------------------------------------------------------------------- /Indicators/IndicatorMovingAverageEnvelope.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace Channels; 7 | 8 | public sealed class IndicatorMovingAverageEnvelope : Indicator, IWatchlistIndicator 9 | { 10 | // Defines the 'Period' parameter as input field (where 'min' is 1 and 'max' is 999). 11 | [InputParameter("Period of MA for envelopes", 0, 1, 999, 1, 0)] 12 | public int Period = 20; 13 | 14 | // Defines the 'SourcePrice' parameter as dropdown list 15 | [InputParameter("Sources prices for MA", 1, variants: new object[] { 16 | "Close", PriceType.Close, 17 | "Open", PriceType.Open, 18 | "High", PriceType.High, 19 | "Low", PriceType.Low, 20 | "Typical", PriceType.Typical, 21 | "Medium", PriceType.Median, 22 | "Weighted", PriceType.Weighted, 23 | "Volume", PriceType.Volume, 24 | "Open interest", PriceType.OpenInterest 25 | })] 26 | public PriceType SourcePrice = PriceType.Close; 27 | 28 | // Defines the 'MaType' parameter as dropdown list 29 | [InputParameter("Type of moving average", 2, variants: new object[]{ 30 | "Simple Moving Average", MaMode.SMA, 31 | "Exponential Moving Average", MaMode.EMA, 32 | "Smoothed Moving Average", MaMode.SMMA, 33 | "Linearly Weighted Moving Average", MaMode.LWMA, 34 | })] 35 | public MaMode MaType = MaMode.SMA; 36 | 37 | [InputParameter("Calculation type", 3, variants: new object[] 38 | { 39 | "All available data", IndicatorCalculationType.AllAvailableData, 40 | "By period", IndicatorCalculationType.ByPeriod, 41 | })] 42 | public IndicatorCalculationType CalculationType = Indicator.DEFAULT_CALCULATION_TYPE; 43 | 44 | // Defines the 'UpShift' parameter as input field (where 'min' is 0.1 and 'increment' is 0.1). 45 | [InputParameter("Upband deviation in %", 4, 0.01, int.MaxValue, 0.01, 2)] 46 | public double UpShift = 0.1; 47 | 48 | // Defines the 'DownShift' parameter as input field (where 'min' is 0.1 and 'increment' is 0.1). 49 | [InputParameter("Downband deviation in %", 5, 0.01, int.MaxValue, 0.01, 2)] 50 | public double DownShift = 0.1; 51 | 52 | public int MinHistoryDepths => this.Period; 53 | public override string ShortName => $"MAE ({this.Period}:{this.UpShift}:{this.DownShift})"; 54 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorMovingAverageEnvelope.cs"; 55 | 56 | private Indicator ma; 57 | 58 | /// 59 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 60 | /// 61 | public IndicatorMovingAverageEnvelope() 62 | : base() 63 | { 64 | // Defines indicator's name and description. 65 | this.Name = "Moving Average Envelope"; 66 | this.Description = "Demonstrates a range of the prices discrepancy from a Moving Average"; 67 | 68 | // Defines two lines with particular parameters. 69 | this.AddLineSeries("Lower Band", Color.Purple, 1, LineStyle.Solid); 70 | this.AddLineSeries("Upper Band", Color.LightSeaGreen, 1, LineStyle.Solid); 71 | 72 | this.SeparateWindow = false; 73 | } 74 | 75 | /// 76 | /// This function will be called after creating an indicator as well as after its input params reset or chart (symbol or timeframe) updates. 77 | /// 78 | protected override void OnInit() 79 | { 80 | // Get MA indicator from built-in indicator collection (according to selected 'MaType'). 81 | this.ma = Core.Indicators.BuiltIn.MA(this.Period, this.SourcePrice, this.MaType, this.CalculationType); 82 | this.AddIndicator(this.ma); 83 | } 84 | 85 | /// 86 | /// Calculation entry point. This function is called when a price data updates. 87 | /// Will be runing under the HistoricalBar mode during history loading. 88 | /// Under NewTick during realtime. 89 | /// Under NewBar if start of the new bar is required. 90 | /// 91 | /// Provides data of updating reason and incoming price. 92 | protected override void OnUpdate(UpdateArgs args) 93 | { 94 | // Skip some period for correct calculation. 95 | if (this.Count < this.MinHistoryDepths) 96 | return; 97 | 98 | // Get current close price (0 offset by default) 99 | double maValue = this.ma.GetValue(); 100 | 101 | // Set values to 'Lower Band' and 'Upper Band' line buffers. 102 | this.SetValue((1.0 - this.DownShift * 0.01) * maValue, 0); 103 | this.SetValue((1.0 + this.UpShift * 0.01) * maValue, 1); 104 | } 105 | } -------------------------------------------------------------------------------- /Indicators/IndicatorSmoothedMovingAverage.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace MovingAverages; 7 | 8 | /// 9 | /// The SMMA gives recent prices an equal weighting to historic prices. 10 | /// 11 | public sealed class IndicatorSmoothedMovingAverage : Indicator, IWatchlistIndicator 12 | { 13 | // Period of moving average. 14 | [InputParameter("Period of Smoothed Moving Average", 0, 1, 999, 1, 0)] 15 | public int MaPeriod = 7; 16 | 17 | // Price type of moving average. 18 | [InputParameter("Sources prices for MA", 1, variants: new object[] 19 | { 20 | "Close", PriceType.Close, 21 | "Open", PriceType.Open, 22 | "High", PriceType.High, 23 | "Low", PriceType.Low, 24 | "Typical", PriceType.Typical, 25 | "Median", PriceType.Median, 26 | "Weighted", PriceType.Weighted, 27 | "Volume", PriceType.Volume, 28 | "Open interest", PriceType.OpenInterest 29 | })] 30 | public PriceType SourcePrice = PriceType.Close; 31 | 32 | [InputParameter("Calculation type", 10, variants: new object[] 33 | { 34 | "All available data", IndicatorCalculationType.AllAvailableData, 35 | "By period", IndicatorCalculationType.ByPeriod, 36 | })] 37 | public IndicatorCalculationType CalculationType = Indicator.DEFAULT_CALCULATION_TYPE; 38 | 39 | /// 40 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 41 | /// 42 | public IndicatorSmoothedMovingAverage() 43 | : base() 44 | { 45 | // Defines indicator's group, name and description. 46 | this.Name = "Smoothed Moving Average"; 47 | this.Description = "The SMMA gives recent prices an equal weighting to historic prices."; 48 | 49 | // Defines line on demand with particular parameters. 50 | this.AddLineSeries("SMMA", Color.DodgerBlue, 1, LineStyle.Solid); 51 | 52 | this.SeparateWindow = false; 53 | } 54 | 55 | public int MinHistoryDepths => this.MaPeriod * 2; 56 | public override string ShortName => $"SMMA ({this.MaPeriod}: {this.SourcePrice})"; 57 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorSmoothedMovingAverage.cs"; 58 | 59 | /// 60 | /// Calculation entry point. This function is called when a price data updates. 61 | /// Will be runing under the HistoricalBar mode during history loading. 62 | /// Under NewTick during realtime. 63 | /// Under NewBar if start of the new bar is required. 64 | /// 65 | /// Provides data of updating reason and incoming price. 66 | protected override void OnUpdate(UpdateArgs args) 67 | { 68 | // Checking, if current amount of bars less, than period of moving average - calculation is impossible. 69 | if (this.Count < this.MinHistoryDepths) 70 | return; 71 | 72 | if (this.CalculationType == IndicatorCalculationType.ByPeriod) 73 | this.CalculateByPeriod(); 74 | else 75 | this.CalculateForAllData(); 76 | } 77 | 78 | private void CalculateByPeriod(int offset = 0) 79 | { 80 | int startOffset = offset + this.MaPeriod; 81 | 82 | if (this.Count <= startOffset + this.MaPeriod) 83 | return; 84 | 85 | // calcualte start value 86 | double smma = this.CalculateSMA(startOffset); 87 | 88 | for (int i = startOffset - 1; i >= offset; i--) 89 | smma = this.CalculateSMMA(i, smma); 90 | 91 | this.SetValue(smma, offset); 92 | } 93 | 94 | private double CalculateSMMA(int offset, double prevSMMA) => (prevSMMA * (this.MaPeriod - 1) + this.GetPrice(this.SourcePrice, offset)) / this.MaPeriod; 95 | 96 | private void CalculateForAllData() 97 | { 98 | // Calculating the current value of the indicator. 99 | double value; 100 | double prevSMMA = this.GetValue(1); 101 | 102 | if (double.IsNaN(prevSMMA)) 103 | { 104 | // Calculates initial value as Simple Moving Average. 105 | value = this.CalculateSMA(0); 106 | } 107 | else 108 | { 109 | value = this.CalculateSMMA(0, prevSMMA); 110 | } 111 | 112 | // Sets value for displaying on the chart. 113 | this.SetValue(value); 114 | } 115 | 116 | private double CalculateSMA(int offset) 117 | { 118 | double sum = 0d; 119 | for (int i = 0; i < this.MaPeriod; i++) 120 | sum += this.GetPrice(this.SourcePrice, offset + i); 121 | 122 | return sum / this.MaPeriod; 123 | } 124 | } -------------------------------------------------------------------------------- /Indicators/IndicatorMovingAverageOfOscillator.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System; 4 | using System.Drawing; 5 | using TradingPlatform.BusinessLayer; 6 | 7 | namespace Oscillators; 8 | 9 | public sealed class IndicatorMovingAverageOfOscillator : Indicator, IWatchlistIndicator 10 | { 11 | // Displays Input Parameter as input field (or checkbox if value type is bolean). 12 | [InputParameter("Period of fast EMA", 0, 1, 999, 1, 0)] 13 | public int FastPeriod = 12; 14 | 15 | [InputParameter("Period of slow EMA", 1, 1, 999, 1, 0)] 16 | public int SlowPeriod = 26; 17 | 18 | [InputParameter("Period of signal EMA", 2, 1, 999, 1, 0)] 19 | public int SignalPeriod = 9; 20 | 21 | // 22 | [InputParameter("Calculation type", 10, variants: new object[] 23 | { 24 | "All available data", IndicatorCalculationType.AllAvailableData, 25 | "By period", IndicatorCalculationType.ByPeriod, 26 | })] 27 | public IndicatorCalculationType CalculationType = Indicator.DEFAULT_CALCULATION_TYPE; 28 | 29 | private int MaxEMAPeriod => Math.Max(this.FastPeriod, this.SlowPeriod); 30 | public int MinHistoryDepths => this.MaxEMAPeriod + this.SignalPeriod; 31 | public override string ShortName => $"OsMA ({this.FastPeriod}:{this.SlowPeriod}:{this.SignalPeriod})"; 32 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorMovingAverageOfOscillator.cs"; 33 | 34 | private Indicator fastEMA; 35 | private Indicator slowEMA; 36 | private Indicator sma; 37 | private HistoricalDataCustom customHD; 38 | 39 | /// 40 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 41 | /// 42 | public IndicatorMovingAverageOfOscillator() 43 | : base() 44 | { 45 | // Defines indicator's name and description. 46 | this.Name = "Moving Average of Oscillator"; 47 | this.Description = "Reflects the difference between an oscillator (MACD) and its moving average (signal line)."; 48 | 49 | // Defines line on demand with particular parameters. 50 | this.AddLineSeries("OsMA", Color.Green, 4, LineStyle.Histogramm); 51 | 52 | this.SeparateWindow = true; 53 | } 54 | 55 | /// 56 | /// This function will be called after creating an indicator as well as after its input params reset or chart (symbol or timeframe) updates. 57 | /// 58 | protected override void OnInit() 59 | { 60 | // Get two EMA and one SMA indicators from built-in indicator collection 61 | this.fastEMA = Core.Indicators.BuiltIn.EMA(this.FastPeriod, PriceType.Typical, this.CalculationType); 62 | this.slowEMA = Core.Indicators.BuiltIn.EMA(this.SlowPeriod, PriceType.Typical, this.CalculationType); 63 | this.sma = Core.Indicators.BuiltIn.SMA(this.SignalPeriod, PriceType.Close); 64 | 65 | // Create a custom HistoricalData and syncronize it with this(MACD) indicator. 66 | this.customHD = new HistoricalDataCustom(this); 67 | 68 | // Attach SMA indicator to custom HistoricalData. The SMA will calculate on the data, which will store in custom HD. 69 | this.customHD.AddIndicator(this.sma); 70 | 71 | // Add auxiliary EMA indicators to the current one. 72 | this.AddIndicator(this.fastEMA); 73 | this.AddIndicator(this.slowEMA); 74 | } 75 | 76 | /// 77 | /// Calculation entry point. This function is called when a price data updates. 78 | /// Will be runing under the HistoricalBar mode during history loading. 79 | /// Under NewTick during realtime. 80 | /// Under NewBar if start of the new bar is required. 81 | /// 82 | /// Provides data of updating reason and incoming price. 83 | protected override void OnUpdate(UpdateArgs args) 84 | { 85 | // Skip max period for correct calculation. 86 | if (this.Count < this.MaxEMAPeriod) 87 | return; 88 | 89 | // Calculate a difference bettwen two EMA indicators. 90 | double differ = this.fastEMA.GetValue() - this.slowEMA.GetValue(); 91 | 92 | // The calculated value must be set as close price against the custom HistoricalData, 93 | // because the SMA indicator was initialized with the source price - PriceType.Close. 94 | this.customHD[PriceType.Close, 0] = differ; 95 | 96 | if (this.Count < this.MinHistoryDepths) 97 | return; 98 | 99 | // Get value from SMA indicator, which is calculated based on custom HistoricalData. 100 | double signal = this.sma.GetValue(); 101 | if (double.IsNaN(signal)) 102 | return; 103 | 104 | // Set value to the 'OsMA' line buffer. 105 | this.SetValue(differ - signal); 106 | } 107 | } -------------------------------------------------------------------------------- /Indicators/IndicatorQstick.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace Oscillators; 7 | 8 | /// 9 | /// Moving average that shows the difference between the prices at which an issue opens and closes. 10 | /// 11 | public sealed class IndicatorQstick : Indicator, IWatchlistIndicator 12 | { 13 | // Displays Input Parameter as input field (or checkbox if value type is bolean). 14 | [InputParameter("Period", 0, 1, 999, 0, 0)] 15 | public int Period = 14; 16 | 17 | // Displays Input Parameter as dropdown list. 18 | [InputParameter("Type of Moving Average", 1, variants: new object[] { 19 | "Simple", MaMode.SMA, 20 | "Exponential", MaMode.EMA, 21 | "Modified", MaMode.SMMA, 22 | "Linear Weighted", MaMode.LWMA} 23 | )] 24 | public MaMode MAType = MaMode.SMA; 25 | [InputParameter("Smoothing period", 0, 1, 999, 0, 0)] 26 | public int SmoothingPeriod = 20; 27 | 28 | // Displays Input Parameter as dropdown list. 29 | [InputParameter("Smoothing Type", 1, variants: new object[] { 30 | "Simple", MaMode.SMA, 31 | "Exponential", MaMode.EMA, 32 | "Modified", MaMode.SMMA, 33 | "Linear Weighted", MaMode.LWMA} 34 | )] 35 | public MaMode SmoothingType = MaMode.SMA; 36 | // 37 | [InputParameter("Calculation type", 5, variants: new object[] 38 | { 39 | "All available data", IndicatorCalculationType.AllAvailableData, 40 | "By period", IndicatorCalculationType.ByPeriod, 41 | })] 42 | public IndicatorCalculationType CalculationType = Indicator.DEFAULT_CALCULATION_TYPE; 43 | 44 | public int MinHistoryDepths => this.Period; 45 | public override string ShortName => $"Qstick ({this.Period}: {this.MAType})"; 46 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorQstick.cs"; 47 | 48 | private HistoricalDataCustom customHistData; 49 | private Indicator ma; 50 | private Indicator smoothing; 51 | 52 | 53 | /// 54 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 55 | /// 56 | public IndicatorQstick() 57 | : base() 58 | { 59 | // Defines indicator's group, name and description. 60 | this.Name = "Qstick"; 61 | this.Description = "Moving average that shows the difference between the prices at which an issue opens and closes."; 62 | 63 | // Defines line on demand with particular parameters. 64 | this.AddLineSeries("Qstick'Line", Color.Blue, 1, LineStyle.Solid); 65 | this.AddLineLevel(0, "0'Line", Color.Gray, 1, LineStyle.Solid); 66 | this.AddLineSeries("Smoothing line", Color.IndianRed, 1, LineStyle.Solid); 67 | 68 | this.SeparateWindow = true; 69 | } 70 | 71 | /// 72 | /// This function will be called after creating an indicator as well as after its input params reset or chart (symbol or timeframe) updates. 73 | /// 74 | protected override void OnInit() 75 | { 76 | // Creates an instance of the custom historical data which will be syncronized by the current indicator instance. 77 | this.customHistData = new HistoricalDataCustom(this); 78 | 79 | // Creates a smoothing indicator which will keep smoothed custom data. 80 | this.ma = Core.Indicators.BuiltIn.MA(this.Period, PriceType.Close, this.MAType, this.CalculationType); 81 | 82 | // Adds the smoothing indicator to the custom historical data. 83 | this.customHistData.AddIndicator(this.ma); 84 | 85 | this.smoothing = Core.Indicators.BuiltIn.MA(this.SmoothingPeriod, PriceType.Open, this.SmoothingType, this.CalculationType); 86 | this.customHistData.AddIndicator(this.smoothing); 87 | } 88 | 89 | /// 90 | /// Calculation entry point. This function is called when a price data updates. 91 | /// Will be runing under the HistoricalBar mode during history loading. 92 | /// Under NewTick during realtime. 93 | /// Under NewBar if start of the new bar is required. 94 | /// 95 | /// Provides data of updating reason and incoming price. 96 | protected override void OnUpdate(UpdateArgs args) 97 | { 98 | // Populates custom HistoricalData price with the current price difference value. 99 | this.customHistData[PriceType.Close] = this.Close() - this.Open(); 100 | 101 | // Skip if count is smaller than period value. 102 | if (this.Count < this.MinHistoryDepths) 103 | return; 104 | var qStickValue = this.ma.GetValue(); 105 | this.customHistData[PriceType.Open] = this.Close() - this.Open(); 106 | // Sets value (smoothing value on the custom historical data) for displaying on the chart. 107 | this.SetValue(qStickValue); 108 | this.SetValue(this.smoothing.GetValue(), 1); 109 | } 110 | } -------------------------------------------------------------------------------- /Indicators/IndicatorBollingerBandsFlat.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace Channels; 7 | 8 | /// 9 | /// The Bollinger Bands Flat (BBF) indicator provides the same data as BB, but drawn in separate field and easier to recognize whether price is in or out of the band. 10 | /// 11 | public sealed class IndicatorBollingerBandsFlat : Indicator, IWatchlistIndicator 12 | { 13 | #region Parameters 14 | 15 | // Displays Input Parameter as input field (or checkbox if value type is bolean). 16 | [InputParameter("Period", 0, 1, 999, 1, 0)] 17 | public int Period = 9; 18 | 19 | [InputParameter("Type of Moving Average", 1, variants: new object[] { 20 | "Simple", MaMode.SMA, 21 | "Exponential", MaMode.EMA, 22 | "Modified", MaMode.SMMA, 23 | "Linear Weighted", MaMode.LWMA} 24 | )] 25 | public MaMode MAType = MaMode.SMA; 26 | 27 | // Displays Input Parameter as dropdown list. 28 | [InputParameter("Sources prices for MA", 2, variants: new object[] { 29 | "Close", PriceType.Close, 30 | "Open", PriceType.Open, 31 | "High", PriceType.High, 32 | "Low", PriceType.Low, 33 | "Typical", PriceType.Typical, 34 | "Medium", PriceType.Median, 35 | "Weighted", PriceType.Weighted, 36 | "Volume", PriceType.Volume, 37 | "Open interest", PriceType.OpenInterest 38 | })] 39 | public PriceType SourcePrice = PriceType.Close; 40 | 41 | [InputParameter("Deviation", 3, 0.01, 3, 0.01, 2)] 42 | public double Deviation = 1.5; 43 | // 44 | [InputParameter("Calculation type", 4, variants: new object[] 45 | { 46 | "All available data", IndicatorCalculationType.AllAvailableData, 47 | "By period", IndicatorCalculationType.ByPeriod, 48 | })] 49 | public IndicatorCalculationType CalculationType = Indicator.DEFAULT_CALCULATION_TYPE; 50 | 51 | #endregion 52 | 53 | // Holds additional indicators values. 54 | private Indicator ma; 55 | private Indicator sd; 56 | public int MinHistoryDepths => this.Period; 57 | public override string ShortName => $"BBF ({this.Period}: {this.Deviation})"; 58 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorBollingerBandsFlat.cs"; 59 | 60 | /// 61 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 62 | /// 63 | public IndicatorBollingerBandsFlat() 64 | : base() 65 | { 66 | // Defines indicator's group, name and description. 67 | this.Name = "Bollinger Bands Flat"; 68 | this.Description = "The Bollinger Bands Flat (BBF) indicator provides the same data as BB, but drawn in separate field and easier to recognize whether price is in or out of the band."; 69 | 70 | // Defines line on demand with particular parameters. 71 | this.AddLineSeries("+SD", Color.Red, 1, LineStyle.Solid); 72 | this.AddLineSeries("-SD", Color.Red, 1, LineStyle.Solid); 73 | this.AddLineSeries("BBF'Line", Color.FromArgb(0, 51, 252), 1, LineStyle.Solid); 74 | this.AddLineLevel(0, "0'Line", Color.Aqua, 1, LineStyle.Solid); 75 | 76 | this.SeparateWindow = true; 77 | } 78 | 79 | /// 80 | /// This function will be called after creating an indicator as well as after its input params reset or chart (symbol or timeframe) updates. 81 | /// 82 | protected override void OnInit() 83 | { 84 | // Creates an instances of the proper indicators (MA, SD) from the default indicators list. 85 | this.ma = Core.Indicators.BuiltIn.MA(this.Period, this.SourcePrice, this.MAType, this.CalculationType); 86 | this.sd = Core.Indicators.BuiltIn.SD(this.Period, this.SourcePrice, this.MAType, this.CalculationType); 87 | // Adds auxiliary (MA, SD) indicators to the current one (BBF). 88 | // This will let inner indicators (MA, SD) to be calculated in advance to the current one (BBF). 89 | this.AddIndicator(this.ma); 90 | this.AddIndicator(this.sd); 91 | } 92 | 93 | /// 94 | /// Calculation entry point. This function is called when a price data updates. 95 | /// Will be runing under the HistoricalBar mode during history loading. 96 | /// Under NewTick during realtime. 97 | /// Under NewBar if start of the new bar is required. 98 | /// 99 | /// Provides data of updating reason and incoming price. 100 | protected override void OnUpdate(UpdateArgs args) 101 | { 102 | if (this.Count < this.MinHistoryDepths) 103 | return; 104 | 105 | // Sets value for displaying on the chart. 106 | double std = this.Deviation * this.sd.GetValue(); 107 | 108 | this.SetValue(std); 109 | this.SetValue(-std, 1); 110 | this.SetValue(this.GetPrice(PriceType.Close) - this.ma.GetValue(), 2); 111 | } 112 | } -------------------------------------------------------------------------------- /Indicators/IndicatorCommodityChannelIndex.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System; 4 | using System.Drawing; 5 | using TradingPlatform.BusinessLayer; 6 | 7 | namespace Oscillators; 8 | 9 | public sealed class IndicatorCommodityChannelIndex : Indicator, IWatchlistIndicator 10 | { 11 | // Displays Input Parameter as input field (or checkbox if value type is bolean). 12 | [InputParameter("Period", 10, 1, 999, 1, 0)] 13 | public int Period = 14; 14 | 15 | // Displays Input Parameter as dropdown list. 16 | [InputParameter("Sources prices for MA", 20, variants: new object[] { 17 | "Close", PriceType.Close, 18 | "Open", PriceType.Open, 19 | "High", PriceType.High, 20 | "Low", PriceType.Low, 21 | "Typical", PriceType.Typical, 22 | "Medium", PriceType.Median, 23 | "Weighted", PriceType.Weighted, 24 | "Volume", PriceType.Volume, 25 | "Open interest", PriceType.OpenInterest 26 | })] 27 | public PriceType SourcePrice = PriceType.Typical; 28 | 29 | // Displays Input Parameter as dropdown list. 30 | [InputParameter("Type of Moving Average", 30, variants: new object[] { 31 | "Simple", MaMode.SMA, 32 | "Exponential", MaMode.EMA, 33 | "Modified", MaMode.SMMA, 34 | "Linear Weighted", MaMode.LWMA} 35 | )] 36 | public MaMode MAType = MaMode.SMA; 37 | 38 | [InputParameter("Calculation type", 40, variants: new object[] 39 | { 40 | "All available data", IndicatorCalculationType.AllAvailableData, 41 | "By period", IndicatorCalculationType.ByPeriod, 42 | })] 43 | public IndicatorCalculationType CalculationType = Indicator.DEFAULT_CALCULATION_TYPE; 44 | 45 | public int MinHistoryDepths => this.Period; 46 | public override string ShortName => $"CCI ({this.Period}: {this.SourcePrice})"; 47 | public override string HelpLink => "https://help.quantower.com/analytics-panels/chart/technical-indicators/oscillators/commodity-channel-index"; 48 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorCommodityChannelIndex.cs"; 49 | 50 | private Indicator MA; 51 | 52 | /// 53 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 54 | /// 55 | public IndicatorCommodityChannelIndex() 56 | : base() 57 | { 58 | // Serves for an identification of related indicators with different parameters. 59 | this.Name = "Commodity Channel Index"; 60 | this.Description = "Measures the position of price in relation to its moving average"; 61 | 62 | // Defines line on demand with particular parameters. 63 | this.AddLineSeries("CCI Line", Color.Red, 1, LineStyle.Solid); 64 | this.AddLineLevel(150, "150", Color.Gray, 1, LineStyle.Solid); 65 | this.AddLineLevel(100, "100", Color.Gray, 1, LineStyle.Solid); 66 | this.AddLineLevel(0, "0", Color.Gray, 1, LineStyle.Solid); 67 | this.AddLineLevel(-100, "-100", Color.Gray, 1, LineStyle.Solid); 68 | this.AddLineLevel(-150, "-150", Color.Gray, 1, LineStyle.Solid); 69 | this.SeparateWindow = true; 70 | } 71 | 72 | /// 73 | /// This function will be called after creating an indicator as well as after its input params reset or chart (symbol or timeframe) updates. 74 | /// 75 | protected override void OnInit() 76 | { 77 | // Creates an instance of the proper indicator from the default indicators list. 78 | this.MA = Core.Indicators.BuiltIn.MA(this.Period, this.SourcePrice, this.MAType, this.CalculationType); 79 | // Adds an auxiliary (MA) indicator to the current one (CCI). 80 | // This will let inner indicator (MA) to be calculated in advance to the current one (CCI). 81 | this.AddIndicator(this.MA); 82 | } 83 | /// 84 | /// Calculation entry point. This function is called when a price data updates. 85 | /// Will be runing under the HistoricalBar mode during history loading. 86 | /// Under NewTick during realtime. 87 | /// Under NewBar if start of the new bar is required. 88 | /// 89 | /// Provides data of updating reason and incoming price. 90 | protected override void OnUpdate(UpdateArgs args) 91 | { 92 | // Skip if count is smaller than period value. 93 | if (this.Count < this.MinHistoryDepths) 94 | return; 95 | 96 | double meanDeviation = 0; 97 | double sma = this.MA.GetValue(0); 98 | for (int i = 0; i < this.Period; i++) 99 | { 100 | double tp = this.GetPrice(this.SourcePrice, i); 101 | meanDeviation += Math.Abs(tp - sma); 102 | } 103 | 104 | meanDeviation = 0.015 * (meanDeviation / this.Period); 105 | 106 | double currentTP = this.GetPrice(this.SourcePrice); 107 | double currentSMA = this.MA.GetValue(); 108 | 109 | this.SetValue((currentTP - currentSMA) / meanDeviation); 110 | } 111 | } -------------------------------------------------------------------------------- /Indicators/IndicatorKeltnerChannel.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace Channels; 7 | 8 | /// 9 | /// Keltner Channels are volatility-based envelopes set above and below an exponential moving average. 10 | /// 11 | public sealed class IndicatorKeltnerChannel : Indicator, IWatchlistIndicator 12 | { 13 | // Displays Input Parameter as input field (or checkbox if value type is bolean). 14 | [InputParameter("Sources prices for MA", 10, variants: new object[] { 15 | "Close", PriceType.Close, 16 | "Open", PriceType.Open, 17 | "High", PriceType.High, 18 | "Low", PriceType.Low, 19 | "Typical", PriceType.Typical, 20 | "Medium", PriceType.Median, 21 | "Weighted", PriceType.Weighted, 22 | "Volume", PriceType.Volume, 23 | "Open interest", PriceType.OpenInterest 24 | })] 25 | public PriceType SourcePrice = PriceType.Close; 26 | 27 | // Displays Input Parameter as input field (or checkbox if value type is bolean). 28 | [InputParameter("Type of Moving Average", 20, variants: new object[] { 29 | "Simple", MaMode.SMA, 30 | "Exponential", MaMode.EMA, 31 | "Modified", MaMode.SMMA, 32 | "Linear Weighted", MaMode.LWMA} 33 | )] 34 | public MaMode MAType = MaMode.SMA; 35 | // 36 | [InputParameter("Calculation type", 30, variants: new object[] 37 | { 38 | "All available data", IndicatorCalculationType.AllAvailableData, 39 | "By period", IndicatorCalculationType.ByPeriod, 40 | })] 41 | public IndicatorCalculationType CalculationType = Indicator.DEFAULT_CALCULATION_TYPE; 42 | 43 | // Displays Input Parameter as dropdown list. 44 | [InputParameter("Period of MA for Keltner's Channel", 40, 1, 9999, 1)] 45 | public int Period = 20; 46 | 47 | // Displays Input Parameter as dropdown list. 48 | [InputParameter("Coefficient of channel's width", 50, 0.01, 100)] 49 | public double Offset = 2; 50 | 51 | public int MinHistoryDepths => this.Period; 52 | public override string ShortName => $"Keltner ({this.Period}: {this.Offset}: {this.SourcePrice}: {this.MAType})"; 53 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorKeltnerChannel.cs"; 54 | 55 | private Indicator ma; 56 | private Indicator atr; 57 | 58 | /// 59 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 60 | /// 61 | public IndicatorKeltnerChannel() 62 | : base() 63 | { 64 | // Defines indicator's group, name and description. 65 | this.Name = "Keltner Channel"; 66 | this.Description = "Keltner Channels are volatility-based envelopes set above and below an exponential moving average"; 67 | this.IsUpdateTypesSupported = false; 68 | 69 | // Defines line on demand with particular parameters. 70 | this.AddLineSeries("MA'Line", Color.Coral, 1, LineStyle.Solid); 71 | this.AddLineSeries("+ATR'Line", Color.Red, 1, LineStyle.Solid); 72 | this.AddLineSeries("-ATR'Line", Color.Purple, 1, LineStyle.Solid); 73 | } 74 | 75 | /// 76 | /// This function will be called after creating an indicator as well as after its input params reset or chart (symbol or timeframe) updates. 77 | /// 78 | protected override void OnInit() 79 | { 80 | // Creates an instances of the proper indicators from the default indicators list. 81 | this.ma = Core.Indicators.BuiltIn.MA(this.Period, this.SourcePrice, this.MAType, this.CalculationType); 82 | this.ma.UpdateType = IndicatorUpdateType.OnTick; 83 | 84 | this.atr = Core.Indicators.BuiltIn.ATR(this.Period, this.MAType, this.CalculationType); 85 | 86 | // Adds an auxiliary (MA, ATR ) indicators to the current one (Keltner). 87 | // This will let inner indicator (MA, ATR) to be calculated in advance to the current one (Keltner). 88 | this.AddIndicator(this.ma); 89 | this.AddIndicator(this.atr); 90 | } 91 | 92 | /// 93 | /// Calculation entry point. This function is called when a price data updates. 94 | /// Will be runing under the HistoricalBar mode during history loading. 95 | /// Under NewTick during realtime. 96 | /// Under NewBar if start of the new bar is required. 97 | /// 98 | /// Provides data of updating reason and incoming price. 99 | protected override void OnUpdate(UpdateArgs args) 100 | { 101 | if (this.Count < this.MinHistoryDepths) 102 | return; 103 | 104 | // Gets calculation values. 105 | double maValue = this.ma.GetValue(); 106 | double atrValue = this.Offset * this.atr.GetValue(); 107 | 108 | // Sets given values for the displaying on the chart. 109 | this.SetValue(maValue, 0); 110 | this.SetValue(maValue + atrValue, 1); 111 | this.SetValue(maValue - atrValue, 2); 112 | } 113 | } -------------------------------------------------------------------------------- /Indicators/Indicator3MASignal.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using TradingPlatform.BusinessLayer; 4 | using System.Drawing; 5 | using System.Linq; 6 | 7 | namespace MovingAverages; 8 | 9 | #warning Не використовуйте абревіатури у назвах, особливо якщо якщо вони не загальноприйняті 10 | public sealed class Indicator3MASignal : Indicator, IWatchlistIndicator 11 | { 12 | private const int UP = 1; // Up trend 13 | private const int DOWN = -1; // Down trend 14 | private const int NONE = 0; // No trend 15 | 16 | //Defines input parameters as input fields 17 | [InputParameter("Short Moving Average Period", 0, 1, 999, 1, 0)] 18 | public int ShortMaPeriod; 19 | 20 | [InputParameter("Middle Moving Average Period", 1, 1, 999, 1, 0)] 21 | public int MiddleMaPeriod; 22 | 23 | [InputParameter("Long Moving Average Period", 2, 1, 999, 1, 0)] 24 | public int LongMaPeriod; 25 | 26 | [InputParameter("Amount of bars passed before opening position", 3, 1, 999, 1, 0)] 27 | public int BarsInterval; 28 | 29 | private Indicator shortMa; 30 | private Indicator middleMa; 31 | private Indicator longMa; 32 | private int currentTrend; 33 | 34 | public int MinHistoryDepths => Enumerable.Max(new int[] { this.ShortMaPeriod, this.MiddleMaPeriod, this.LongMaPeriod }); 35 | public override string ShortName => $"MAS3 ({this.ShortMaPeriod}:{this.MiddleMaPeriod}:{this.LongMaPeriod}:{this.BarsInterval})"; 36 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/Indicator3MASignal.cs"; 37 | 38 | /// 39 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 40 | /// 41 | public Indicator3MASignal() 42 | { 43 | // Defines indicator's name and description. 44 | this.Name = "3MASignal"; 45 | this.Description = "Offers buy and sell signals according to intersections of three moving averages"; 46 | 47 | this.ShortMaPeriod = 5; 48 | this.MiddleMaPeriod = 10; 49 | this.LongMaPeriod = 25; 50 | this.BarsInterval = 1; 51 | 52 | this.SeparateWindow = true; 53 | 54 | // Define one line with particular parameters 55 | this.AddLineSeries("3MASignal", Color.Orange, 5, LineStyle.Histogramm); 56 | } 57 | 58 | /// 59 | /// This function will be called after creating an indicator as well as after its input params reset or chart (symbol or timeframe) updates. 60 | /// 61 | protected override void OnInit() 62 | { 63 | this.currentTrend = NONE; 64 | 65 | // Get SMA indicators from built-in indicator collection 66 | this.shortMa = Core.Indicators.BuiltIn.MA(this.ShortMaPeriod, PriceType.Close, MaMode.SMA); 67 | this.middleMa = Core.Indicators.BuiltIn.MA(this.MiddleMaPeriod, PriceType.Close, MaMode.SMA); 68 | this.longMa = Core.Indicators.BuiltIn.MA(this.LongMaPeriod, PriceType.Close, MaMode.SMA); 69 | 70 | this.AddIndicator(this.shortMa); 71 | this.AddIndicator(this.middleMa); 72 | this.AddIndicator(this.longMa); 73 | } 74 | 75 | /// 76 | /// Calculation entry point. This function is called when a price data updates. 77 | /// Will be runing under the HistoricalBar mode during history loading. 78 | /// Under NewTick during realtime. 79 | /// Under NewBar if start of the new bar is required. 80 | /// 81 | /// Provides data of updating reason and incoming price. 82 | protected override void OnUpdate(UpdateArgs args) 83 | { 84 | // Skip largest period for correct calculation. 85 | if (this.Count < this.MinHistoryDepths) 86 | return; 87 | 88 | // Define the trend on the interval 89 | for (int shift = 0; shift < this.BarsInterval; shift++) 90 | { 91 | if (shift == 0) 92 | { 93 | // Calculate the initial state 94 | this.currentTrend = CompareMA(this.shortMa.GetValue(shift, 0), this.middleMa.GetValue(shift, 0), this.longMa.GetValue(shift, 0)); 95 | } 96 | else 97 | { 98 | int trend = CompareMA(this.shortMa.GetValue(shift, 0), this.middleMa.GetValue(shift, 0), this.longMa.GetValue(shift, 0)); 99 | 100 | if (trend != this.currentTrend) 101 | { 102 | this.currentTrend = NONE; 103 | break; 104 | } 105 | } 106 | } 107 | // Set price to the line buffer (line index is 0) by offset 0; 108 | this.SetValue(this.currentTrend); 109 | } 110 | 111 | /// 112 | /// Compare SMA values for define current trend 113 | /// 114 | /// ShortMA value 115 | /// MiddleMa value 116 | /// LongMa value 117 | /// Current trend (as int) 118 | private static int CompareMA(double shMa, double midMA, double lgMa) 119 | { 120 | if (midMA > lgMa && midMA < shMa) 121 | return UP; 122 | else if (midMA > shMa && midMA < lgMa) 123 | return DOWN; 124 | 125 | return NONE; 126 | } 127 | } -------------------------------------------------------------------------------- /Indicators/IndicatorPercentagePriceOscillator.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System; 4 | using System.Drawing; 5 | using TradingPlatform.BusinessLayer; 6 | 7 | namespace Oscillators; 8 | 9 | /// 10 | /// Percentage Price Oscillator is a momentum indicator. Signal line is EMA of PPO. Formula: (FastEMA-SlowEMA)/SlowEMA 11 | /// 12 | public sealed class IndicatorPercentagePriceOscillator : Indicator, IWatchlistIndicator 13 | { 14 | // Displays Input Parameter as input field (or checkbox if value type is bolean). 15 | [InputParameter("Fast EMA Period", 0, 1, 999, 1, 0)] 16 | public int fastEmaPeriod = 12; 17 | 18 | [InputParameter("Slow EMA Period", 1, 1, 999, 1, 0)] 19 | public int slowEmaPeriod = 26; 20 | 21 | [InputParameter("Signal EMA Period", 2, 1, 999, 1, 0)] 22 | public int signalEmaPeriod = 9; 23 | // 24 | [InputParameter("Calculation type", 5, variants: new object[] 25 | { 26 | "All available data", IndicatorCalculationType.AllAvailableData, 27 | "By period", IndicatorCalculationType.ByPeriod, 28 | })] 29 | public IndicatorCalculationType CalculationType = Indicator.DEFAULT_CALCULATION_TYPE; 30 | 31 | private int MaxEMAPeriod => Math.Max(this.fastEmaPeriod, this.slowEmaPeriod); 32 | public int MinHistoryDepths => this.MaxEMAPeriod + this.signalEmaPeriod; 33 | public override string ShortName => $"PPO ({this.fastEmaPeriod}: {this.slowEmaPeriod}: {this.signalEmaPeriod})"; 34 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorPercentagePriceOscillator.cs"; 35 | 36 | private Indicator fastEma; 37 | private Indicator slowEma; 38 | private Indicator signalEma; 39 | private HistoricalDataCustom customHDsignal; 40 | 41 | /// 42 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 43 | /// 44 | public IndicatorPercentagePriceOscillator() 45 | : base() 46 | { 47 | // Defines indicator's group, name and description. 48 | this.Name = "Percentage Price Oscillator"; 49 | this.Description = "Percentage Price Oscillator is a momentum indicator. Signal line is EMA of PPO. Formula: (FastEMA-SlowEMA)/SlowEMA"; 50 | 51 | // Defines line on demand with particular parameters. 52 | this.AddLineSeries("PPO'Line", Color.SkyBlue, 2, LineStyle.Solid); 53 | this.AddLineSeries("Signal'Line", Color.Red, 1, LineStyle.Solid); 54 | this.AddLineLevel(0, "0'Line", Color.Gray, 1, LineStyle.Solid); 55 | 56 | this.SeparateWindow = true; 57 | } 58 | 59 | /// 60 | /// This function will be called after creating an indicator as well as after its input params reset or chart (symbol or timeframe) updates. 61 | /// 62 | protected override void OnInit() 63 | { 64 | // Creates an instance of the custom historical data which will be syncronized by the current indicator instance. 65 | this.customHDsignal = new HistoricalDataCustom(this); 66 | 67 | // Creates a smoothing indicator which will keep smoothed custom data (for close prices). 68 | this.signalEma = Core.Indicators.BuiltIn.EMA(this.signalEmaPeriod, PriceType.Close, this.CalculationType); 69 | 70 | // Adds the smoothing indicator to the custom historical data. 71 | this.customHDsignal.AddIndicator(this.signalEma); 72 | 73 | // Creates an instances of the proper indicators from the default indicators list. 74 | this.fastEma = Core.Indicators.BuiltIn.EMA(this.fastEmaPeriod, PriceType.Close, this.CalculationType); 75 | this.slowEma = Core.Indicators.BuiltIn.EMA(this.slowEmaPeriod, PriceType.Close, this.CalculationType); 76 | 77 | // Adds an auxiliary (fastEMA, slowEMA) indicators to the current one (PPO). 78 | // This will let inner indicators (fastEMA, slowEMA) to be calculated in advance to the current one (PPO). 79 | this.AddIndicator(this.fastEma); 80 | this.AddIndicator(this.slowEma); 81 | } 82 | 83 | /// 84 | /// Calculation entry point. This function is called when a price data updates. 85 | /// Will be runing under the HistoricalBar mode during history loading. 86 | /// Under NewTick during realtime. 87 | /// Under NewBar if start of the new bar is required. 88 | /// 89 | /// Provides data of updating reason and incoming price. 90 | protected override void OnUpdate(UpdateArgs args) 91 | { 92 | if (this.Count < this.MaxEMAPeriod) 93 | return; 94 | 95 | // Gets calculation values. 96 | double fastEMA = this.fastEma.GetValue(); 97 | double slowEMA = this.slowEma.GetValue(); 98 | 99 | // Gets PPO value. 100 | double ppo = (fastEMA - slowEMA) / slowEMA; 101 | 102 | // Populates custom HistoricalData price with the PPO value. 103 | this.customHDsignal[PriceType.Close] = ppo; 104 | 105 | // Skip if count is smaller than period value. 106 | if (this.Count < this.MinHistoryDepths) 107 | return; 108 | 109 | // Sets given values for the displaying on the chart. 110 | this.SetValue(ppo, 0); 111 | this.SetValue(this.signalEma.GetValue(), 1); 112 | } 113 | } -------------------------------------------------------------------------------- /Indicators/IndicatorExponentialMovingAverage.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Drawing; 4 | using TradingPlatform.BusinessLayer; 5 | 6 | namespace MovingAverages; 7 | 8 | /// 9 | /// The weighted price calculation for the last N periods. 10 | /// 11 | public sealed class IndicatorExponentialMovingAverage : Indicator, IWatchlistIndicator 12 | { 13 | // Period of moving average. 14 | [InputParameter("Period of Exponential Moving Average", 10, 1, 9999, 1, 0)] 15 | public int MaPeriod = 9; 16 | 17 | // Price type of moving average. 18 | [InputParameter("Sources prices for MA", 20, variants: new object[] 19 | { 20 | "Close", PriceType.Close, 21 | "Open", PriceType.Open, 22 | "High", PriceType.High, 23 | "Low", PriceType.Low, 24 | "Typical", PriceType.Typical, 25 | "Median", PriceType.Median, 26 | "Weighted", PriceType.Weighted, 27 | "Volume", PriceType.Volume, 28 | "Open interest", PriceType.OpenInterest 29 | })] 30 | public PriceType SourcePrice = PriceType.Close; 31 | 32 | // 33 | [InputParameter("Calculation type", 30, variants: new object[] 34 | { 35 | "All available data", IndicatorCalculationType.AllAvailableData, 36 | "By period", IndicatorCalculationType.ByPeriod, 37 | })] 38 | public IndicatorCalculationType CalculationType = Indicator.DEFAULT_CALCULATION_TYPE; 39 | 40 | public int MinHistoryDepths => this.CalculationType switch 41 | { 42 | IndicatorCalculationType.AllAvailableData => this.MaPeriod, 43 | _ => this.MaPeriod * 2 44 | }; 45 | public override string ShortName => $"EMA ({this.MaPeriod}: {this.SourcePrice})"; 46 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorExponentialMovingAverage.cs"; 47 | 48 | // EMA's calculation coefficient 49 | private double k; 50 | 51 | /// 52 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 53 | /// 54 | public IndicatorExponentialMovingAverage() 55 | : base() 56 | { 57 | // Defines indicator's group, name and description. 58 | this.Name = "Exponential Moving Average"; 59 | this.Description = "The weighted price calculation for the last N periods"; 60 | 61 | // Defines line on demand with particular parameters. 62 | this.AddLineSeries("EMA", Color.DodgerBlue, 1, LineStyle.Solid); 63 | 64 | this.SeparateWindow = false; 65 | } 66 | 67 | /// 68 | /// This function will be called after creating an indicator as well as after its input params reset or chart (symbol or timeframe) updates. 69 | /// 70 | protected override void OnInit() 71 | { 72 | // Calculation of a coefficient. 73 | this.k = 2.0 / (this.MaPeriod + 1); 74 | } 75 | /// 76 | /// Calculation entry point. This function is called when a price data updates. 77 | /// Will be runing under the HistoricalBar mode during history loading. 78 | /// Under NewTick during realtime. 79 | /// Under NewBar if start of the new bar is required. 80 | /// 81 | /// Provides data of updating reason and incoming price. 82 | protected override void OnUpdate(UpdateArgs args) 83 | { 84 | if (this.CalculationType == IndicatorCalculationType.ByPeriod) 85 | this.CalculateByPeriod(); 86 | else 87 | this.CalcualteForAllData(); 88 | } 89 | 90 | private void CalcualteForAllData(int offset = 0) 91 | { 92 | if (this.Count <= offset + 1) 93 | return; 94 | 95 | int prevOffset = offset + 1; 96 | 97 | // Getting previous EMA and display value. If it's NaN (start calculation) then get current close price (by default). 98 | double prevEMA = double.IsNaN(this.GetValue(prevOffset)) 99 | ? this.GetPrice(this.SourcePrice, prevOffset) 100 | : this.GetValue(prevOffset); 101 | 102 | double ema = this.CalculateEMA(offset, prevEMA); 103 | 104 | if (this.Count <= this.MaPeriod) 105 | return; 106 | 107 | this.SetValue(ema); 108 | } 109 | private void CalculateByPeriod(int offset = 0) 110 | { 111 | int startOffset = offset + this.MaPeriod; 112 | 113 | if (this.Count <= startOffset + this.MaPeriod) 114 | return; 115 | 116 | // Calculate start value 117 | double ema = this.CalculateSMA(startOffset); 118 | 119 | for (int i = startOffset - 1; i >= offset; i--) 120 | ema = this.CalculateEMA(i, ema); 121 | 122 | this.SetValue(ema, 0, offset); 123 | } 124 | 125 | private double CalculateEMA(int offset, double prevEMA) 126 | { 127 | // Getting current price. 128 | double price = this.GetPrice(this.SourcePrice, offset); 129 | 130 | // Sets value for displaying on the chart. 131 | return prevEMA + this.k * (price - prevEMA); 132 | } 133 | private double CalculateSMA(int offset) 134 | { 135 | double sum = 0d; 136 | for (int i = 0; i < this.MaPeriod; i++) 137 | sum += this.GetPrice(this.SourcePrice, offset + i); 138 | 139 | return sum / this.MaPeriod; 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /Indicators/IndicatorATRTrailingStopWithFibRetracements.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System; 4 | using System.Drawing; 5 | using TradingPlatform.BusinessLayer; 6 | 7 | namespace Volatility; 8 | 9 | public class IndicatorATRTrailingStopWithFibRetracements : Indicator 10 | { 11 | [InputParameter("ATR Period", 0, 1, 9999)] 12 | public int Period = 5; 13 | [InputParameter("ATR Factor", 0, 0.1, 999, 0.1, 1)] 14 | public double ATRFactor = 3.5; 15 | [InputParameter("Fib1", 0, 0.1, 999, 0.1, 1)] 16 | public double Fib1Lvl = 61.8; 17 | [InputParameter("Fib2", 0, 0.1, 999, 0.1, 1)] 18 | public double Fib2Lvl = 78.6; 19 | [InputParameter("Fib3", 0, 0.1, 999, 0.1, 1)] 20 | public double Fib3Lvl = 88.6; 21 | [InputParameter("Type of Moving Average", 3, variants: new object[] { 22 | "Simple", MaMode.SMA, 23 | "Exponential", MaMode.EMA, 24 | "Smoothed Modified", MaMode.SMMA, 25 | "Linear Weighted", MaMode.LWMA})] 26 | public MaMode MaType = MaMode.SMA; 27 | 28 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorATRTrailingStopWithFibRetracements.cs"; 29 | 30 | 31 | public double fibLvl1 = 1.618, fibLvl2 = 2.618, fibLvl3 = 4.23, fib1, fib2, fib3, fibTgt1, fibTgt2, fibTgt3; 32 | public double trailStop, trend, trendUp, trendDown, ex, currClose, switchVal, diff, loss; 33 | public bool trendChange; 34 | private Indicator atr; 35 | public override string ShortName => $"ATRTrailStop ({this.Period})"; 36 | public IndicatorATRTrailingStopWithFibRetracements() 37 | : base() 38 | { 39 | // Defines indicator's name and description. 40 | Name = "ATR Trailing w/Fib Targets"; 41 | Description = "Fib Targets on the ATR trailing stop"; 42 | 43 | // Defines line on demand with particular parameters. 44 | AddLineSeries("TrailStop", Color.White, 1, LineStyle.Solid); 45 | AddLineSeries("fibTgtDown1", Color.Red, 1, LineStyle.Solid); 46 | AddLineSeries("fibTgtDown2", Color.Red, 1, LineStyle.Solid); 47 | AddLineSeries("fibTgtDown3", Color.Red, 1, LineStyle.Solid); 48 | AddLineSeries("fibTgtUp1", Color.Green, 1, LineStyle.Solid); 49 | AddLineSeries("fibTgtUp2", Color.Green, 1, LineStyle.Solid); 50 | AddLineSeries("fibTgtUp3", Color.Green, 1, LineStyle.Solid); 51 | AddLineSeries("fib1", Color.Gray, 1, LineStyle.Solid); 52 | AddLineSeries("fib2", Color.Gray, 1, LineStyle.Solid); 53 | AddLineSeries("fib3", Color.Gray, 1, LineStyle.Solid); 54 | // By default indicator will be applied on main window of the chart 55 | SeparateWindow = false; 56 | } 57 | 58 | protected override void OnInit() 59 | { 60 | this.atr = Core.Indicators.BuiltIn.ATR(this.Period, this.MaType, Indicator.DEFAULT_CALCULATION_TYPE); 61 | this.AddIndicator(this.atr); 62 | } 63 | 64 | protected override void OnUpdate(UpdateArgs args) 65 | { 66 | double prevClose = currClose; 67 | 68 | currClose = GetPrice(PriceType.Close); 69 | double currHigh = GetPrice(PriceType.High); 70 | double currLow = GetPrice(PriceType.Low); 71 | 72 | loss = ATRFactor * atr.GetValue(); 73 | double up = currClose - loss; 74 | double down = currClose + loss; 75 | 76 | double prevTrend = trend; 77 | double prevTrendUp = trendUp; 78 | double prevTrendDown = trendDown; 79 | 80 | trendUp = prevClose > prevTrendUp ? Math.Max(up, prevTrendUp) : up; 81 | trendDown = prevClose < prevTrendDown ? Math.Min(down, prevTrendDown) : down; 82 | trend = currClose > prevTrendDown ? 1 : currClose < prevTrendUp ? -1 : prevTrend; 83 | 84 | trailStop = trend == 1 ? trendUp : trendDown; 85 | 86 | double prevEx = ex; 87 | ex = (trend > 0 && prevTrend < 0) ? currHigh : (trend < 0 && prevTrend > 0) ? currLow : trend == 1 ? Math.Max(prevEx, currHigh) : trend == -1 ? Math.Min(prevEx, currLow) : prevEx; 88 | 89 | fib1 = ex + (trailStop - ex) * Fib1Lvl / 100; 90 | fib2 = ex + (trailStop - ex) * Fib2Lvl / 100; 91 | fib3 = ex + (trailStop - ex) * Fib3Lvl / 100; 92 | 93 | double prevSwitchVal = switchVal; 94 | double prevDiff = diff; 95 | trendChange = trend == prevTrend ? false : true; 96 | switchVal = trendChange ? trailStop : prevSwitchVal; 97 | diff = trendChange ? currClose - switchVal : prevDiff; 98 | 99 | fibTgt1 = switchVal + (diff * fibLvl1); 100 | fibTgt2 = switchVal + (diff * fibLvl2); 101 | fibTgt3 = switchVal + (diff * fibLvl3); 102 | double prevfibTgt1 = fibTgt1; 103 | 104 | SetValue(trailStop); 105 | if (trend == 1 && fibTgt1 == prevfibTgt1) 106 | { 107 | if (fibTgt1 > trailStop) 108 | SetValue(fibTgt1, 4); 109 | if (fibTgt2 > trailStop) 110 | SetValue(fibTgt2, 5); 111 | if (fibTgt3 > trailStop) 112 | SetValue(fibTgt3, 6); 113 | } 114 | if (trend == -1 && fibTgt1 == prevfibTgt1) 115 | { 116 | if (fibTgt1 < trailStop) 117 | SetValue(fibTgt1, 1); 118 | if (fibTgt2 < trailStop) 119 | SetValue(fibTgt2, 2); 120 | if (fibTgt3 < trailStop) 121 | SetValue(fibTgt3, 3); 122 | } 123 | SetValue(fib1, 7); 124 | SetValue(fib2, 8); 125 | SetValue(fib3, 9); 126 | } 127 | } -------------------------------------------------------------------------------- /Indicators/IndicatorIchimoku.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System; 4 | using System.Drawing; 5 | using TradingPlatform.BusinessLayer; 6 | 7 | namespace Trend; 8 | 9 | public sealed class IndicatorIchimoku : Indicator, IWatchlistIndicator 10 | { 11 | private const int TENKAN = 0; 12 | private const int KIJUN = 1; 13 | private const int SENKOU_SPANA = 2; 14 | private const int SENKOU_SPANB = 3; 15 | private const int CHINKOU_SPAN = 4; 16 | 17 | // Displays Input Parameter as input field (or checkbox if value type is bolean). 18 | [InputParameter("Tenkan Sen", 0, 1, 9999, 1, 0)] 19 | public int TenkanPeriod = 9; 20 | 21 | [InputParameter("Kijun Sen", 1, 1, 9999, 1, 0)] 22 | public int KijunPeriod = 26; 23 | 24 | [InputParameter("Senkou Span B", 2, 1, 9999, 1, 0)] 25 | public int SenkouSpanB = 52; 26 | 27 | [InputParameter("Cloud up color", 3)] 28 | public Color UpColor = Color.FromArgb(50, Color.Green); 29 | 30 | [InputParameter("Cloud down color", 3)] 31 | public Color DownColor = Color.FromArgb(50, Color.Red); 32 | 33 | public override string ShortName => $"ICH ({this.TenkanPeriod}: {this.KijunPeriod}: {this.SenkouSpanB})"; 34 | public int MinHistoryDepths => Math.Max(this.TenkanPeriod, Math.Max(this.KijunPeriod, this.SenkouSpanB)); 35 | public override string HelpLink => "https://help.quantower.com/analytics-panels/chart/technical-indicators/trend/ichimoku-indicator"; 36 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorIchimoku.cs"; 37 | 38 | private Trend currentTrend; 39 | 40 | /// 41 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 42 | /// 43 | public IndicatorIchimoku() 44 | : base() 45 | { 46 | // Defines indicator's name and description. 47 | this.Name = "Ichimoku"; 48 | this.Description = "Enables to quickly discern and filter 'at a glance' the low-probability trading setups from those of higher probability"; 49 | 50 | // Defines line on demand with particular parameters. 51 | this.AddLineSeries("Tenkan", Color.Blue, 1, LineStyle.Solid); 52 | this.AddLineSeries("Kijun", Color.Lime, 1, LineStyle.Solid); 53 | this.AddLineSeries("Senkou Span A", Color.SpringGreen, 1, LineStyle.Solid); 54 | this.AddLineSeries("Senkou Span B", Color.Red, 1, LineStyle.Solid); 55 | this.AddLineSeries("Chinkou Span", Color.FromArgb(255, 153, 0), 1, LineStyle.Solid); 56 | 57 | this.SeparateWindow = false; 58 | } 59 | 60 | /// 61 | /// This function will be called after creating an indicator as well as after its input params reset or chart (symbol or timeframe) updates. 62 | /// 63 | protected override void OnInit() 64 | { 65 | this.LinesSeries[SENKOU_SPANA].TimeShift = this.KijunPeriod; 66 | this.LinesSeries[SENKOU_SPANB].TimeShift = this.KijunPeriod; 67 | this.LinesSeries[CHINKOU_SPAN].TimeShift = -this.KijunPeriod; 68 | } 69 | 70 | /// 71 | /// Calculation entry point. This function is called when a price data updates. 72 | /// Will be runing under the HistoricalBar mode during history loading. 73 | /// Under NewTick during realtime. 74 | /// Under NewBar if start of the new bar is required. 75 | /// 76 | /// Provides data of updating reason and incoming price. 77 | protected override void OnUpdate(UpdateArgs args) 78 | { 79 | if (this.Count < this.MinHistoryDepths) 80 | return; 81 | 82 | //1 line 83 | this.SetValue(this.GetAverage(this.TenkanPeriod), TENKAN); 84 | 85 | //2 line 86 | this.SetValue(this.GetAverage(this.KijunPeriod), KIJUN); 87 | 88 | //5 line 89 | this.SetValue(this.GetPrice(PriceType.Close), CHINKOU_SPAN); 90 | 91 | //3 line 92 | double senkouSpanA = (this.GetValue(0, TENKAN) + this.GetValue(0, KIJUN)) / 2; 93 | this.SetValue(senkouSpanA, SENKOU_SPANA); 94 | 95 | //4 line 96 | double senkouSpanB = this.GetAverage(this.SenkouSpanB); 97 | this.SetValue(senkouSpanB, SENKOU_SPANB); 98 | 99 | var newTrend = senkouSpanA == senkouSpanB ? Trend.Unknown : 100 | senkouSpanA > senkouSpanB ? Trend.Up : Trend.Down; 101 | 102 | if (this.currentTrend != newTrend) 103 | { 104 | this.EndCloud(SENKOU_SPANA, SENKOU_SPANB, this.GetColorByTrend(this.currentTrend)); 105 | this.BeginCloud(SENKOU_SPANA, SENKOU_SPANB, this.GetColorByTrend(newTrend)); 106 | } 107 | 108 | this.currentTrend = newTrend; 109 | } 110 | 111 | public double GetAverage(int period) 112 | { 113 | double high = this.GetPrice(PriceType.High); 114 | double low = this.GetPrice(PriceType.Low); 115 | for (int i = 1; i < period; i++) 116 | { 117 | double price = this.GetPrice(PriceType.High, i); 118 | if (high < price) 119 | high = price; 120 | price = this.GetPrice(PriceType.Low, i); 121 | if (low > price) 122 | low = price; 123 | } 124 | 125 | return (high + low) / 2.0; 126 | } 127 | 128 | private Color GetColorByTrend(Trend trend) => trend switch 129 | { 130 | Trend.Up => this.UpColor, 131 | Trend.Down => this.DownColor, 132 | _ => Color.Empty 133 | }; 134 | 135 | private enum Trend 136 | { 137 | Unknown, 138 | Up, 139 | Down 140 | } 141 | } -------------------------------------------------------------------------------- /Indicators/IndicatorDeltaFlow.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Drawing; 6 | using TradingPlatform.BusinessLayer; 7 | 8 | namespace VolumeIndicators; 9 | 10 | public class IndicatorDeltaFlow : Indicator, IVolumeAnalysisIndicator, IWatchlistIndicator 11 | { 12 | #region Parameters 13 | public const string COLORING_SCHEME_SI = "Coloring scheme"; 14 | 15 | public override string HelpLink => "https://help.quantower.com/analytics-panels/chart/technical-indicators/volume/delta-flow"; 16 | 17 | [InputParameter(COLORING_SCHEME_SI, 10, variants: new object[] 18 | { 19 | "By delta", DeltaPaceColoringScheme.ByDelta, 20 | "By bar", DeltaPaceColoringScheme.ByBar 21 | })] 22 | internal DeltaPaceColoringScheme ColoringScheme = DeltaPaceColoringScheme.ByDelta; 23 | 24 | internal PairColor PairColor; 25 | 26 | private bool isVolumeAnalysisProgressSubscribed; 27 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorDeltaFlow.cs"; 28 | 29 | #endregion Parameters 30 | 31 | public IndicatorDeltaFlow() 32 | { 33 | this.Name = "Delta Flow"; 34 | this.AddLineSeries("Histogram", Color.Gray, 3, LineStyle.Histogramm); 35 | this.IsUpdateTypesSupported = false; 36 | 37 | this.PairColor = new PairColor() 38 | { 39 | Color1 = Color.FromArgb(33, 150, 243), 40 | Color2 = Color.FromArgb(239, 83, 80), 41 | Text1 = loc._("Up"), 42 | Text2 = loc._("Down") 43 | }; 44 | this.SeparateWindow = true; 45 | } 46 | 47 | #region Overrides 48 | protected override void OnInit() 49 | { 50 | this.isVolumeAnalysisProgressSubscribed = false; 51 | } 52 | protected override void OnUpdate(UpdateArgs args) 53 | { 54 | // 55 | if (!this.isVolumeAnalysisProgressSubscribed) 56 | { 57 | if (this.HistoricalData?.VolumeAnalysisCalculationProgress != null) 58 | { 59 | this.HistoricalData.VolumeAnalysisCalculationProgress.ProgressChanged += VolumeAnalysisCalculationProgress_ProgressChanged; 60 | this.isVolumeAnalysisProgressSubscribed = true; 61 | } 62 | } 63 | 64 | this.CalculateIndicatorByOffset(offset: 0); 65 | } 66 | public override IList Settings 67 | { 68 | get 69 | { 70 | var settings = base.Settings; 71 | 72 | var inputSepar = settings.GetItemByName(COLORING_SCHEME_SI)?.SeparatorGroup ?? new SettingItemSeparatorGroup(); 73 | 74 | settings.Add(new SettingItemPairColor("HistogramColors", this.PairColor, 10) 75 | { 76 | SeparatorGroup = inputSepar, 77 | Text = loc._("Histogram colors") 78 | }); 79 | 80 | return settings; 81 | } 82 | set 83 | { 84 | base.Settings = value; 85 | 86 | if (value.GetItemByName("HistogramColors") is SettingItemPairColor pairColorSI) 87 | { 88 | this.PairColor = (PairColor)pairColorSI.Value; 89 | this.Refresh(); 90 | } 91 | } 92 | } 93 | protected override void OnClear() 94 | { 95 | if (this.HistoricalData?.VolumeAnalysisCalculationProgress != null) 96 | this.HistoricalData.VolumeAnalysisCalculationProgress.ProgressChanged -= VolumeAnalysisCalculationProgress_ProgressChanged; 97 | } 98 | #endregion Overrides 99 | 100 | #region Misc and Event handlers 101 | private void CalculateIndicatorByOffset(int offset) 102 | { 103 | var index = this.Count - 1 - offset; 104 | if (index < 0) 105 | return; 106 | 107 | var volumeAnalysis = this.HistoricalData[index, SeekOriginHistory.Begin].VolumeAnalysisData; 108 | 109 | if (volumeAnalysis != null) 110 | { 111 | var value = volumeAnalysis.Total.Delta * (this.High(offset) - this.Low(offset)); 112 | this.SetValue(Math.Abs(value), 0, offset); 113 | 114 | var isUpColor = 115 | (ColoringScheme == DeltaPaceColoringScheme.ByDelta && volumeAnalysis.Total.Delta > 0) || 116 | (ColoringScheme == DeltaPaceColoringScheme.ByBar && this.Close(offset) > this.Open(offset)); 117 | 118 | if (isUpColor) 119 | this.LinesSeries[0].SetMarker(offset, this.PairColor.Color1); 120 | else 121 | this.LinesSeries[0].SetMarker(offset, this.PairColor.Color2); 122 | } 123 | } 124 | private void RecalculateAllIndicator() 125 | { 126 | for (int i = 0; i < this.Count - 1; i++) 127 | this.CalculateIndicatorByOffset(i); 128 | } 129 | 130 | private void VolumeAnalysisCalculationProgress_ProgressChanged(object sender, VolumeAnalysisTaskEventArgs e) 131 | { 132 | if (e.CalculationState == VolumeAnalysisCalculationState.Processing) 133 | this.RecalculateAllIndicator(); 134 | } 135 | #endregion Misc and Event handlers 136 | 137 | #region IVolumeAnalysisIndicator 138 | public bool IsRequirePriceLevelsCalculation => false; 139 | public void VolumeAnalysisData_Loaded() 140 | { 141 | this.RecalculateAllIndicator(); 142 | } 143 | #endregion IVolumeAnalysisIndicator 144 | 145 | #region IWatchlistIndicator 146 | public int MinHistoryDepths => 2; 147 | #endregion IWatchlistIndicator 148 | 149 | internal enum DeltaPaceColoringScheme 150 | { 151 | ByDelta = 0, 152 | ByBar = 10, 153 | } 154 | } -------------------------------------------------------------------------------- /Indicators/IndicatorSeparatedAverageTrueRange.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System.Collections.Generic; 4 | using System.Drawing; 5 | using TradingPlatform.BusinessLayer; 6 | 7 | namespace OscillatorsIndicators; 8 | 9 | public sealed class IndicatorSeparatedAverageTrueRange : Indicator 10 | { 11 | #region Parameters 12 | private const string HISTOGRAM_COLORS_SETTING_NAME = "HistogramColor"; 13 | private const string PERIOD_SETTING_NAME = "Period of Moving Average"; 14 | 15 | [InputParameter(PERIOD_SETTING_NAME, 0, 1, 999, 1, 0)] 16 | public int Period = 14; 17 | 18 | [InputParameter("Type of Moving Average", 1, variants: new object[] { 19 | "Simple", MaMode.SMA, 20 | "Exponential", MaMode.EMA, 21 | "Smoothed", MaMode.SMMA, 22 | "Linear Weighted", MaMode.LWMA} 23 | )] 24 | public MaMode MAType = MaMode.SMA; 25 | 26 | [InputParameter("Calculation type", 5, variants: new object[] 27 | { 28 | "All available data", IndicatorCalculationType.AllAvailableData, 29 | "By period", IndicatorCalculationType.ByPeriod, 30 | })] 31 | public IndicatorCalculationType CalculationType = Indicator.DEFAULT_CALCULATION_TYPE; 32 | 33 | private HistoricalDataCustom customHD1; 34 | private HistoricalDataCustom customHD2; 35 | private Indicator atr1; 36 | private Indicator atr2; 37 | private Color upHistogramColor; 38 | private Color downHistogramColor; 39 | 40 | public override string ShortName => $"SATR ({this.Period}: {this.MAType})"; 41 | 42 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorSeparatedAverageTrueRange.cs"; 43 | 44 | #endregion Parameters 45 | 46 | public IndicatorSeparatedAverageTrueRange() 47 | { 48 | this.Name = "Separated Average True Range"; 49 | 50 | this.upHistogramColor = Color.FromArgb(0, 178, 89); 51 | this.downHistogramColor = Color.FromArgb(251, 87, 87); 52 | 53 | this.AddLineSeries("Buy ATR", this.upHistogramColor, 2, LineStyle.Solid); 54 | this.AddLineSeries("Sell ATR", this.downHistogramColor, 2, LineStyle.Solid); 55 | this.AddLineSeries("Delta", Color.DodgerBlue, 2, LineStyle.Histogramm); 56 | 57 | this.LinesSeries[0].Visible = this.LinesSeries[1].Visible = false; 58 | 59 | this.SeparateWindow = true; 60 | } 61 | 62 | protected override void OnInit() 63 | { 64 | base.OnInit(); 65 | 66 | this.customHD1 = new HistoricalDataCustom(); 67 | this.atr1 = Core.Indicators.BuiltIn.ATR(this.Period, this.MAType, this.CalculationType); 68 | this.customHD1.AddIndicator(this.atr1); 69 | 70 | this.customHD2 = new HistoricalDataCustom(); 71 | this.atr2 = Core.Indicators.BuiltIn.ATR(this.Period, this.MAType, this.CalculationType); 72 | this.customHD2.AddIndicator(this.atr2); 73 | } 74 | 75 | public override IList Settings 76 | { 77 | get 78 | { 79 | var settings = base.Settings; 80 | 81 | var separatorGroup = settings.GetItemByName(PERIOD_SETTING_NAME)?.SeparatorGroup ?? new SettingItemSeparatorGroup(""); 82 | settings.Add(new SettingItemPairColor(HISTOGRAM_COLORS_SETTING_NAME, new PairColor(this.upHistogramColor, this.downHistogramColor, loc._("Up"), loc._("Down")), 10) 83 | { 84 | Text = loc._("Histogram style"), 85 | SeparatorGroup = separatorGroup 86 | }); 87 | return settings; 88 | } 89 | set 90 | { 91 | if (value.GetItemByName(HISTOGRAM_COLORS_SETTING_NAME) is SettingItemPairColor pairColorSI && pairColorSI.Value is PairColor colors) 92 | { 93 | this.upHistogramColor = colors.Color1; 94 | this.downHistogramColor = colors.Color2; 95 | 96 | this.Refresh(); 97 | } 98 | 99 | base.Settings = value; 100 | } 101 | } 102 | 103 | protected override void OnUpdate(UpdateArgs args) 104 | { 105 | if (this.customHD1.Count == 0 || !double.IsNaN(this.customHD1[PriceType.Close]) && args.Reason != UpdateReason.NewTick) 106 | this.customHD1.AddValue(double.NaN, double.NaN, double.NaN, double.NaN); 107 | 108 | if (this.customHD2.Count == 0 || !double.IsNaN(this.customHD2[PriceType.Close]) && args.Reason != UpdateReason.NewTick) 109 | this.customHD2.AddValue(double.NaN, double.NaN, double.NaN, double.NaN); 110 | 111 | if (this.Open() < this.Close()) 112 | { 113 | this.customHD1.SetValue(this.Open(), this.High(), this.Low(), this.Close()); 114 | this.customHD2.SetValue(double.NaN, double.NaN, double.NaN, double.NaN); 115 | } 116 | else 117 | { 118 | this.customHD2.SetValue(this.Open(), this.High(), this.Low(), this.Close()); 119 | this.customHD1.SetValue(double.NaN, double.NaN, double.NaN, double.NaN); 120 | } 121 | 122 | if (this.Count < this.Period) 123 | return; 124 | 125 | double v1 = double.IsNaN(this.atr1.GetValue()) ? this.atr1.GetValue(1) : this.atr1.GetValue(); 126 | double v2 = double.IsNaN(this.atr2.GetValue()) ? this.atr2.GetValue(1) : this.atr2.GetValue(); 127 | 128 | this.SetValue(v1, 0); 129 | this.SetValue(v2, 1); 130 | 131 | double delta = v1 - v2; 132 | this.SetValue(delta, 2); 133 | 134 | if (delta > 0) 135 | this.LinesSeries[2].SetMarker(0, this.upHistogramColor); 136 | else 137 | this.LinesSeries[2].SetMarker(0, this.downHistogramColor); 138 | } 139 | } -------------------------------------------------------------------------------- /Indicators/IndicatorTrueStrengthIndex.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System; 4 | using System.Drawing; 5 | using TradingPlatform.BusinessLayer; 6 | 7 | namespace Oscillators; 8 | 9 | public sealed class IndicatorTrueStrengthIndex : Indicator, IWatchlistIndicator 10 | { 11 | // Displays Input Parameter as input field. 12 | [InputParameter("First MA period", 0, 1, 999, 1, 0)] 13 | public int FirstPeriod = 5; 14 | 15 | // Displays Input Parameter as input field. 16 | [InputParameter("Second MA period", 1, 1, 999, 1, 0)] 17 | public int SecondPeriod = 8; 18 | 19 | // 20 | [InputParameter("Calculation type", 10, variants: new object[] 21 | { 22 | "All available data", IndicatorCalculationType.AllAvailableData, 23 | "By period", IndicatorCalculationType.ByPeriod, 24 | })] 25 | public IndicatorCalculationType CalculationType = Indicator.DEFAULT_CALCULATION_TYPE; 26 | 27 | private Indicator firstEma; 28 | private Indicator firstEmaAbs; 29 | private Indicator secondEma; 30 | private Indicator secondEmaAbs; 31 | 32 | private HistoricalDataCustom firstEmaHD; 33 | private HistoricalDataCustom firstEmaAbsHD; 34 | private HistoricalDataCustom secondEmaHD; 35 | private HistoricalDataCustom secondEmaAbsHD; 36 | 37 | public int MinHistoryDepths => this.FirstPeriod + this.SecondPeriod; 38 | public override string ShortName => $"TSI ({this.FirstPeriod}:{this.SecondPeriod})"; 39 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorTrueStrengthIndex.cs"; 40 | 41 | /// 42 | /// Indicator's constructor. Contains general information: name, description, LineSeries etc. 43 | /// 44 | public IndicatorTrueStrengthIndex() 45 | : base() 46 | { 47 | // Defines indicator's name and description. 48 | this.Name = "True Strength Index"; 49 | this.Description = "Is a variation of the Relative Strength Indicator which uses a doubly-smoothed exponential moving average of price momentum to eliminate choppy price changes and spot trend changes"; 50 | 51 | // Defines lines on demand with particular parameters. 52 | this.AddLineLevel(50, "Upper", Color.Gray, 1, LineStyle.Solid); 53 | this.AddLineLevel(0, "Zero", Color.Gray, 1, LineStyle.Solid); 54 | this.AddLineLevel(-50, "Lower", Color.Gray, 1, LineStyle.Solid); 55 | this.AddLineSeries("TSI", Color.Orange, 1, LineStyle.Solid); 56 | 57 | this.SeparateWindow = true; 58 | } 59 | 60 | /// 61 | /// This function will be called after creating an indicator as well as after its input params reset or chart (symbol or timeframe) updates. 62 | /// 63 | protected override void OnInit() 64 | { 65 | // Get EMA indicators from built-in indicator collection. 66 | this.firstEma = Core.Indicators.BuiltIn.EMA(this.FirstPeriod, PriceType.Close, this.CalculationType); 67 | this.firstEmaAbs = Core.Indicators.BuiltIn.EMA(this.FirstPeriod, PriceType.Close, this.CalculationType); 68 | this.secondEma = Core.Indicators.BuiltIn.EMA(this.SecondPeriod, PriceType.Close, this.CalculationType); 69 | this.secondEmaAbs = Core.Indicators.BuiltIn.EMA(this.SecondPeriod, PriceType.Close, this.CalculationType); 70 | 71 | // Create custom HistoricalData objects for stored custom values and syncronize their with this(TSI) indicator. 72 | this.firstEmaHD = new HistoricalDataCustom(this); 73 | this.firstEmaAbsHD = new HistoricalDataCustom(this); 74 | this.secondEmaHD = new HistoricalDataCustom(this); 75 | this.secondEmaAbsHD = new HistoricalDataCustom(this); 76 | 77 | // Attach EMA indicators to custom HistoricalData. 78 | this.firstEmaHD.AddIndicator(this.firstEma); 79 | this.firstEmaAbsHD.AddIndicator(this.firstEmaAbs); 80 | this.secondEmaHD.AddIndicator(this.secondEma); 81 | this.secondEmaAbsHD.AddIndicator(this.secondEmaAbs); 82 | } 83 | 84 | /// 85 | /// Calculation entry point. This function is called when a price data updates. 86 | /// Will be runing under the HistoricalBar mode during history loading. 87 | /// Under NewTick during realtime. 88 | /// Under NewBar if start of the new bar is required. 89 | /// 90 | /// Provides data of updating reason and incoming price. 91 | protected override void OnUpdate(UpdateArgs args) 92 | { 93 | double mtm = this.GetMTM(0); 94 | 95 | // Store custom value as 'Close' price into custom HD, 96 | // because EMA indicator (which was attached to it) was initialized with PriceType.Close. 97 | this.firstEmaHD[PriceType.Close, 0] = mtm; 98 | this.firstEmaAbsHD[PriceType.Close, 0] = Math.Abs(mtm); 99 | 100 | // Skip some period for correct calculation. 101 | if (this.Count < this.FirstPeriod) 102 | return; 103 | 104 | this.secondEmaHD[PriceType.Close, 0] = this.firstEma.GetValue(); 105 | this.secondEmaAbsHD[PriceType.Close, 0] = this.firstEmaAbs.GetValue(); 106 | 107 | if (this.Count < this.MinHistoryDepths) 108 | return; 109 | 110 | // Set value to 'TSI' line buffer. 111 | this.SetValue(100 * this.secondEma.GetValue() / this.secondEmaAbs.GetValue()); 112 | } 113 | 114 | /// 115 | /// Compute the momentum value. 116 | /// 117 | private double GetMTM(int offset) 118 | { 119 | if (this.Count < 2) 120 | return this.GetPrice(PriceType.Close, offset); 121 | 122 | return this.GetPrice(PriceType.Close, offset) - this.GetPrice(PriceType.Close, offset + 1); 123 | } 124 | } -------------------------------------------------------------------------------- /Indicators/IndicatorRoundNumbers.cs: -------------------------------------------------------------------------------- 1 | // Copyright QUANTOWER LLC. © 2017-2024. All rights reserved. 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Drawing; 6 | using TradingPlatform.BusinessLayer; 7 | using TradingPlatform.BusinessLayer.Utils; 8 | 9 | namespace ChanneIsIndicators; 10 | 11 | public class IndicatorRoundNumbers : Indicator 12 | { 13 | public const string ROUND_NUMBERS_SI = "Step of lines (ticks)"; 14 | public const string NUMBER_OF_LINES_SI = "Number of lines"; 15 | 16 | [InputParameter(ROUND_NUMBERS_SI, 10, 1, int.MaxValue, 1, 0)] 17 | public int Step = 50; 18 | 19 | [InputParameter(NUMBER_OF_LINES_SI, 20, 1, int.MaxValue, 1, 0)] 20 | public int NumberOfLines = 20; 21 | 22 | public override string ShortName => $"{this.Name} ({this.Step})"; 23 | 24 | public LineOptions LineOptions 25 | { 26 | get => this.lineOptions; 27 | set 28 | { 29 | this.lineOptions = value; 30 | this.currentPen = ProcessPen(this.currentPen, value); 31 | } 32 | } 33 | private LineOptions lineOptions; 34 | private Pen currentPen; 35 | 36 | public override string SourceCodeLink => "https://github.com/Quantower/Scripts/blob/main/Indicators/IndicatorRoundNumbers.cs"; 37 | 38 | public IndicatorRoundNumbers() 39 | { 40 | this.Name = "Round numbers"; 41 | 42 | this.LineOptions = new LineOptions() 43 | { 44 | LineStyle = LineStyle.Solid, 45 | Color = Color.Orange, 46 | Width = 2, 47 | WithCheckBox = false, 48 | Enabled = true 49 | }; 50 | 51 | this.OnBackGround = true; 52 | this.SeparateWindow = false; 53 | } 54 | 55 | #region Overrides 56 | 57 | public override void OnPaintChart(PaintChartEventArgs args) 58 | { 59 | var gr = args.Graphics; 60 | 61 | float deltaPriceY = (float)(this.Step * this.CurrentChart.TickSize * this.CurrentChart.MainWindow.YScaleFactor); 62 | if (deltaPriceY <= 0) 63 | return; 64 | 65 | int bottom = this.CurrentChart.MainWindow.ClientRectangle.Bottom; 66 | int top = this.CurrentChart.MainWindow.ClientRectangle.Top; 67 | int right = this.CurrentChart.MainWindow.ClientRectangle.Right; 68 | 69 | double middlePrice = this.Close(); 70 | double correctedMiddleLevel = (int)(middlePrice / (this.Step * this.CurrentChart.TickSize)) * (this.Step * this.CurrentChart.TickSize); 71 | 72 | float startLevel = (float)(this.CurrentChart.MainWindow.CoordinatesConverter.GetChartY(correctedMiddleLevel) - System.Math.Ceiling(this.NumberOfLines / 2d) * deltaPriceY); 73 | 74 | for (int i = 0; i < this.NumberOfLines; i++) 75 | { 76 | if (startLevel >= top && startLevel <= bottom) 77 | gr.DrawLine(this.currentPen, 0f, startLevel, right, startLevel); 78 | 79 | startLevel += deltaPriceY; 80 | } 81 | } 82 | public override IList Settings 83 | { 84 | get 85 | { 86 | var settings = base.Settings; 87 | 88 | var inputParametersSepar = settings.GetItemByName(ROUND_NUMBERS_SI) is SettingItem si 89 | ? si.SeparatorGroup 90 | : new SettingItemSeparatorGroup("", 10); 91 | 92 | settings.Add(new SettingItemLineOptions("LineStyle", this.LineOptions, 10) 93 | { 94 | Text = loc._("Line style"), 95 | SeparatorGroup = inputParametersSepar 96 | }); 97 | 98 | return settings; 99 | } 100 | set 101 | { 102 | base.Settings = value; 103 | 104 | if (value.GetItemByName("LineStyle") is SettingItemLineOptions si) 105 | this.LineOptions = si.Value as LineOptions; 106 | } 107 | } 108 | 109 | #endregion Overrides 110 | 111 | private static Pen ProcessPen(Pen pen, LineOptions lineOptions) 112 | { 113 | if (pen == null) 114 | pen = new Pen(Color.Empty); 115 | 116 | pen.Color = lineOptions.Color; 117 | pen.Width = lineOptions.Width; 118 | 119 | try 120 | { 121 | switch (lineOptions.LineStyle) 122 | { 123 | case LineStyle.Solid: 124 | { 125 | pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Solid; 126 | break; 127 | } 128 | case LineStyle.Dot: 129 | { 130 | pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot; 131 | break; 132 | } 133 | case LineStyle.Dash: 134 | { 135 | pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash; 136 | break; 137 | } 138 | case LineStyle.DashDot: 139 | { 140 | pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Custom; 141 | float[] dp = new float[] { 2, 4, 7, 4 }; 142 | pen.DashPattern = dp; 143 | break; 144 | } 145 | case LineStyle.Histogramm: 146 | { 147 | pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Custom; 148 | float[] dp = new float[] { 0.25F, 1 }; 149 | pen.DashPattern = dp; 150 | pen.Width = 4; 151 | break; 152 | } 153 | } 154 | } 155 | catch (Exception ex) 156 | { 157 | Core.Loggers.Log(ex); 158 | } 159 | return pen; 160 | } 161 | } --------------------------------------------------------------------------------