Skip to content

Instantly share code, notes, and snippets.

@danielnegri
Last active November 20, 2024 21:19
Show Gist options
  • Save danielnegri/3fcf483d0862ae05ef4e9411011bfcb3 to your computer and use it in GitHub Desktop.
Save danielnegri/3fcf483d0862ae05ef4e9411011bfcb3 to your computer and use it in GitHub Desktop.
NinjaTrader 8 - Power Candle Indicator
#region Using declarations
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Xml.Serialization;
using NinjaTrader.Cbi;
using NinjaTrader.Gui;
using NinjaTrader.Gui.Chart;
using NinjaTrader.Gui.SuperDom;
using NinjaTrader.Gui.Tools;
using NinjaTrader.Data;
using NinjaTrader.NinjaScript;
using NinjaTrader.Core.FloatingPoint;
using NinjaTrader.NinjaScript.DrawingTools;
#endregion
//This namespace holds Indicators in this folder and is required. Do not change it.
namespace NinjaTrader.NinjaScript.Indicators
{
public class PowerCandle : Indicator
{
private EMA fastMA;
private SMA sma20;
private SMA volSMA;
private int drawnRanges;
private const int LIMIT_DRAWN_RANGES = 255;
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
Description = @"Displays power candles.";
Name = "Power Candle";
Calculate = Calculate.OnBarClose;
IsOverlay = true;
VolumePeriod = 20;
//Disable this property if your indicator requires custom values that cumulate with each new market data event.
//See Help Guide for additional information.
IsSuspendedWhileInactive = true;
}
else if (State == State.DataLoaded)
{
drawnRanges = 10;
fastMA = EMA(Close, 9);
sma20 = SMA(Close, 20);
volSMA = SMA(Volume, VolumePeriod);
}
}
protected override void OnBarUpdate()
{
if (CurrentBar < 20) return;
// Crossed Moving Averages
double high0 = High[0];
double low0 = Low[0];
double open0 = Open[0];
double close0 = Close[0];
bool crossesfastMA = low0 <= fastMA[0] && fastMA[0] <= high0;
bool crossesSMA20 = low0 <= sma20[0] && sma20[0] <= high0;
bool isUpBar = Open[0] < Close[0];
bool hasBody = Math.Abs(close0 - open0) * 1.67 > (high0 - low0);
// Calculate Volume
bool aboveVolume = IsRising(volSMA) && Volume[0] > (volSMA[0]);
// Bar Brushes
if (aboveVolume && hasBody && crossesfastMA && crossesSMA20)
{
drawRange(isUpBar, Brushes.DarkViolet);
}
else if (aboveVolume && hasBody)
{
drawRange(isUpBar, isUpBar ? Brushes.Green : Brushes.Red);
}
}
private void setBarBrushes(SolidColorBrush up, SolidColorBrush down, bool isUpBar)
{
BarBrushes[0] = isUpBar ? up : down;
}
private void drawRange(bool isUpBar, SolidColorBrush color)
{
string oldTag = "Power Range #" + ((drawnRanges + 1) % LIMIT_DRAWN_RANGES).ToString();
if (DrawObjects[oldTag] != null) RemoveDrawObject(oldTag);
int barAgo = 0;
double range = Instrument.MasterInstrument.RoundToTickSize(High[barAgo] - Low[barAgo]);
string tag = "Power Range #" + drawnRanges.ToString();
drawnRanges = (drawnRanges + 1) % LIMIT_DRAWN_RANGES;
double yOffset = 4;
double y = isUpBar ? Low[barAgo] - yOffset * TickSize : High[barAgo] + yOffset * TickSize;
SimpleFont font = new SimpleFont();
font.Bold = true;
font.Size = 8;
Draw.Text(this, tag, true, range.ToString(), barAgo, y, 0, color, font, TextAlignment.Center, null, color, 20);
}
#region Properties
[Range(3, int.MaxValue), NinjaScriptProperty]
[Display(ResourceType = typeof(Custom.Resource), Name = "Volume Period", GroupName = "NinjaScriptParameters", Order = 0)]
public int VolumePeriod
{ get; set; }
#endregion
}
}
#region NinjaScript generated code. Neither change nor remove.
namespace NinjaTrader.NinjaScript.Indicators
{
public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase
{
private PowerCandle[] cachePowerCandle;
public PowerCandle PowerCandle(int volumePeriod)
{
return PowerCandle(Input, volumePeriod);
}
public PowerCandle PowerCandle(ISeries<double> input, int volumePeriod)
{
if (cachePowerCandle != null)
for (int idx = 0; idx < cachePowerCandle.Length; idx++)
if (cachePowerCandle[idx] != null && cachePowerCandle[idx].VolumePeriod == volumePeriod && cachePowerCandle[idx].EqualsInput(input))
return cachePowerCandle[idx];
return CacheIndicator<PowerCandle>(new PowerCandle(){ VolumePeriod = volumePeriod }, input, ref cachePowerCandle);
}
}
}
namespace NinjaTrader.NinjaScript.MarketAnalyzerColumns
{
public partial class MarketAnalyzerColumn : MarketAnalyzerColumnBase
{
public Indicators.PowerCandle PowerCandle(int volumePeriod)
{
return indicator.PowerCandle(Input, volumePeriod);
}
public Indicators.PowerCandle PowerCandle(ISeries<double> input , int volumePeriod)
{
return indicator.PowerCandle(input, volumePeriod);
}
}
}
namespace NinjaTrader.NinjaScript.Strategies
{
public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase
{
public Indicators.PowerCandle PowerCandle(int volumePeriod)
{
return indicator.PowerCandle(Input, volumePeriod);
}
public Indicators.PowerCandle PowerCandle(ISeries<double> input , int volumePeriod)
{
return indicator.PowerCandle(input, volumePeriod);
}
}
}
#endregion
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment