I could be wrong, but I remember having issue with using system time (now) is that it could be out of sync with bar time. I think getting time from Times[0][0] may be more accurate. Or, compare Times[0][0] to system time, from time to time, and calculate clock drift.
Announcement
Collapse
No announcement yet.
Partner 728x90
Collapse
NinjaTrader
Power of Three (PO3)
Collapse
X
-
Awesome. Would you mind explaining if you are running the timer on UI thread so it updates outside of onbarupdate interval? Wouldn't it also force refresh of the whole chart and slow down NT? I think I've seen similar construct to speed up chart refresh.Originally posted by rockmanx00 View Post
I could be wrong, but I remember having issue with using system time (now) is that it could be out of sync with bar time. I think getting time from Times[0][0] may be more accurate. Or, compare Times[0][0] to system time, from time to time, and calculate clock drift.Last edited by MiCe1999; 02-20-2025, 10:02 AM.
-
Nice. I bought something that almost does the same thing. I think it didn't quite overlay as nicely though, was off slightly so I never used it. Pretty sure I paid about $100 or so for it. Good job.
Leave a comment:
-
Not exactly the same thing, but I wrote an indicator that overlays the range of higher timeframe candles over the current price. Candle bodies are shown in color, the wicks are shown in gray. In this example, these are 15 minute candles overlaid on a 1 minute chart.
- Likes 1
Leave a comment:
-
I haven't thought of that. I could look into figuring out how to add that. I suppose if I were to add that, I could add the bar type and period above the candle, and place the time below so you know what higher time frame candle you are using and how much time for that particular time frame is left...Good idea.
Leave a comment:
-
Thanks for sharing. Clean code, AI has still much to learn.Originally posted by rockmanx00 View PostI attempted to make one too. You can change the colors or the wicks, outline for Up/Down candles, the fill color of those candles, and the ability to choose a bar type and a period. You can also choose not to display the value text on the side....
. Have you thought of adding a countdown timer?
Leave a comment:
-
I attempted to make one too. You can change the colors or the wicks, outline for Up/Down candles, the fill color of those candles, and the ability to choose a bar type and a period. You can also choose not to display the value text on the side....
*Edit*
Added Displays to show the Bar type and period above, and a timer for the higher time frame below. There are also boolean you can uncheck if you don't want them displayed, but are on by default.
Changed some of the formatting so the text and HTF candle centers nicely. Also moved the Open and Low texts to the left side of the candle so they no longer overlap each other.
Fixed more centering issues.
Fixed overlapping issue when displaying price. I didn't check to see it worked with green candles, so I fixed some of the logic and it works now.
Fixed some Properties window formatting and descriptions.
Added a check to ensure that the secondary is a Higher time frame.
The Secondary time frame can be either "Second", "Minute" or "Day" time frames.
If the Secondary time frame chosen is lower than the Primary time frame, or the Primary time frame is not either "Second", "Minute" or "Day" time frames, the indicator will default to the Primary data series data.
Download from the User App Share here: https://ninjatraderecosystem.com/use...-of-three-po3/Last edited by rockmanx00; 02-25-2025, 10:22 AM.
- Likes 1
Leave a comment:
-
Ah, higher time frames is what I should be looking at more often. You can use 240 minutes for the period to get 4H candle, however if you're going as big as 4H - volume profile is probably better to look at. I think this type of indicator could use one or two preceding candles as well.Last edited by MiCe1999; 02-19-2025, 11:06 AM.
Leave a comment:
-
Amazing.Originally posted by MiCe1999 View Post
Since I had few tokens left for today I asked chatGPT to make a cute candle like in your example. It may not have all the null checks but it should give you an idea what's possible:
PHP Code:#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 namespace NinjaTrader.NinjaScript.Indicators { public class MarginCandlestick : Indicator { private int barPaintWidth; private Dictionary<string, DXMediaMap> dxmBrushes; private SharpDX.RectangleF reuseRect; private SharpDX.Vector2 reuseVector1, reuseVector2; private double lastOpen, lastHigh, lastLow, lastClose; protected override void OnStateChange() { if (State == State.SetDefaults) { Description = "Renders a candlestick in the right margin using secondary timeframe data"; Name = "MarginCandlestick"; Calculate = Calculate.OnPriceChange; // Changed from OnBarClose IsOverlay = true; DisplayInDataBox = true; DrawOnPricePanel = true; IsSuspendedWhileInactive = true; Period = 1; // Default 1 minute dxmBrushes = new Dictionary<string, DXMediaMap>(); foreach (string brushName in new string[] { "barColorDown", "barColorUp", "shadowColor" }) dxmBrushes.Add(brushName, new DXMediaMap()); BarColorDown = Brushes.Red; BarColorUp = Brushes.Lime; ShadowColor = (Application.Current.TryFindResource("ChartControl.AxisPen") as Pen).Brush; ShadowWidth = 1; } else if (State == State.Configure) { // Add secondary data series AddDataSeries(BarsPeriodType.Minute, Period); } } protected override void OnBarUpdate() { try { if (BarsInProgress != 1) return; if (CurrentBars[0] < 0 || CurrentBars[1] < 0 || BarsArray[1].Count <= 0) return; // Get current candle data using [0][0] lastOpen = Opens[1][0]; lastHigh = Highs[1][0]; lastLow = Lows[1][0]; lastClose = Closes[1][0]; // Debug output //Print($"Current Candle - O: {lastOpen}, H: {lastHigh}, L: {lastLow}, C: {lastClose}"); } catch (Exception ex) { Print($"MarginCandlestick OnBarUpdate Error: {ex.Message}"); } } protected override void OnRender(ChartControl chartControl, ChartScale chartScale) { if (RenderTarget == null || chartControl == null || chartScale == null) return; barPaintWidth = Math.Max(6, 1 + 2 * ((int)ChartBars.Properties.ChartStyle.BarWidth - 1) + 2 * ShadowWidth); // Calculate x position in margin int x = chartControl.CanvasRight - 40; // Get y-coordinates using stored secondary series data int y1 = chartScale.GetYByValue(lastOpen); int y2 = chartScale.GetYByValue(lastHigh); int y3 = chartScale.GetYByValue(lastLow); int y4 = chartScale.GetYByValue(lastClose); // Draw shadow line reuseVector1.X = x; reuseVector1.Y = y2; reuseVector2.X = x; reuseVector2.Y = y3; RenderTarget.DrawLine(reuseVector1, reuseVector2, dxmBrushes["shadowColor"].DxBrush); // Draw body if (lastClose == lastOpen) { // Draw horizontal line for doji reuseVector1.X = (x - barPaintWidth / 2); reuseVector1.Y = y1; reuseVector2.X = (x + barPaintWidth / 2); reuseVector2.Y = y1; RenderTarget.DrawLine(reuseVector1, reuseVector2, dxmBrushes["shadowColor"].DxBrush); } else { // Draw candlestick body if (lastClose > lastOpen) { UpdateRect(ref reuseRect, (x - barPaintWidth / 2), y4, barPaintWidth, (y1 - y4)); RenderTarget.FillRectangle(reuseRect, dxmBrushes["barColorUp"].DxBrush); } else { UpdateRect(ref reuseRect, (x - barPaintWidth / 2), y1, barPaintWidth, (y4 - y1)); RenderTarget.FillRectangle(reuseRect, dxmBrushes["barColorDown"].DxBrush); } // Draw border UpdateRect(ref reuseRect, ((x - barPaintWidth / 2) + (ShadowWidth / 2)), Math.Min(y4, y1), (barPaintWidth - ShadowWidth + 2), Math.Abs(y4 - y1)); RenderTarget.DrawRectangle(reuseRect, dxmBrushes["shadowColor"].DxBrush); } } public override void OnRenderTargetChanged() { try { foreach (KeyValuePair<string, DXMediaMap> item in dxmBrushes) { if (item.Value.DxBrush != null) item.Value.DxBrush.Dispose(); if (RenderTarget != null) item.Value.DxBrush = item.Value.MediaBrush.ToDxBrush(RenderTarget); } } catch (Exception exception) { Print($"MarginCandlestick OnRenderTargetChanged Error: {exception.Message}"); } } private void UpdateRect(ref SharpDX.RectangleF rectangle, float x, float y, float width, float height) { rectangle.X = x; rectangle.Y = y; rectangle.Width = width; rectangle.Height = height; } #region Properties [Browsable(false)] public class DXMediaMap { public SharpDX.Direct2D1.Brush DxBrush; public System.Windows.Media.Brush MediaBrush; } [NinjaScriptProperty] [Range(1, int.MaxValue)] [Display(Name="Period (Minutes)", Order=1, GroupName="Parameters")] public int Period { get; set; } [NinjaScriptProperty] [XmlIgnore] [Display(Name="BarColorDown", Order=2, GroupName="Parameters")] public Brush BarColorDown { get { return dxmBrushes["barColorDown"].MediaBrush; } set { dxmBrushes["barColorDown"].MediaBrush = value; } } [Browsable(false)] public string BarColorDownSerializable { get { return Serialize.BrushToString(BarColorDown); } set { BarColorDown = Serialize.StringToBrush(value); } } [NinjaScriptProperty] [XmlIgnore] [Display(Name="BarColorUp", Order=3, GroupName="Parameters")] public Brush BarColorUp { get { return dxmBrushes["barColorUp"].MediaBrush; } set { dxmBrushes["barColorUp"].MediaBrush = value; } } [Browsable(false)] public string BarColorUpSerializable { get { return Serialize.BrushToString(BarColorUp); } set { BarColorUp = Serialize.StringToBrush(value); } } [NinjaScriptProperty] [XmlIgnore] [Display(Name="ShadowColor", Order=4, GroupName="Parameters")] public Brush ShadowColor { get { return dxmBrushes["shadowColor"].MediaBrush; } set { dxmBrushes["shadowColor"].MediaBrush = value; } } [Browsable(false)] public string ShadowColorSerializable { get { return Serialize.BrushToString(ShadowColor); } set { ShadowColor = Serialize.StringToBrush(value); } } [NinjaScriptProperty] [Range(1, int.MaxValue)] [Display(Name="ShadowWidth", Order=5, GroupName="Parameters")] public int ShadowWidth { get; set; } #endregion } }​
By the way, the candle displayed within my screenshot is a 4H candle. Thanks!
Leave a comment:
-
Since I had few tokens left for today I asked chatGPT to make a cute candle like in your example. It may not have all the null checks but it should give you an idea what's possible:Originally posted by michelz View Post
Thanks! This is helpful.
PHP Code:#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 namespace NinjaTrader.NinjaScript.Indicators { public class MarginCandlestick : Indicator { private int barPaintWidth; private Dictionary<string, DXMediaMap> dxmBrushes; private SharpDX.RectangleF reuseRect; private SharpDX.Vector2 reuseVector1, reuseVector2; private double lastOpen, lastHigh, lastLow, lastClose; protected override void OnStateChange() { if (State == State.SetDefaults) { Description = "Renders a candlestick in the right margin using secondary timeframe data"; Name = "MarginCandlestick"; Calculate = Calculate.OnPriceChange; // Changed from OnBarClose IsOverlay = true; DisplayInDataBox = true; DrawOnPricePanel = true; IsSuspendedWhileInactive = true; Period = 1; // Default 1 minute dxmBrushes = new Dictionary<string, DXMediaMap>(); foreach (string brushName in new string[] { "barColorDown", "barColorUp", "shadowColor" }) dxmBrushes.Add(brushName, new DXMediaMap()); BarColorDown = Brushes.Red; BarColorUp = Brushes.Lime; ShadowColor = (Application.Current.TryFindResource("ChartControl.AxisPen") as Pen).Brush; ShadowWidth = 1; } else if (State == State.Configure) { // Add secondary data series AddDataSeries(BarsPeriodType.Minute, Period); } } protected override void OnBarUpdate() { try { if (BarsInProgress != 1) return; if (CurrentBars[0] < 0 || CurrentBars[1] < 0 || BarsArray[1].Count <= 0) return; // Get current candle data using [0][0] lastOpen = Opens[1][0]; lastHigh = Highs[1][0]; lastLow = Lows[1][0]; lastClose = Closes[1][0]; // Debug output //Print($"Current Candle - O: {lastOpen}, H: {lastHigh}, L: {lastLow}, C: {lastClose}"); } catch (Exception ex) { Print($"MarginCandlestick OnBarUpdate Error: {ex.Message}"); } } protected override void OnRender(ChartControl chartControl, ChartScale chartScale) { if (RenderTarget == null || chartControl == null || chartScale == null) return; barPaintWidth = Math.Max(6, 1 + 2 * ((int)ChartBars.Properties.ChartStyle.BarWidth - 1) + 2 * ShadowWidth); // Calculate x position in margin int x = chartControl.CanvasRight - 40; // Get y-coordinates using stored secondary series data int y1 = chartScale.GetYByValue(lastOpen); int y2 = chartScale.GetYByValue(lastHigh); int y3 = chartScale.GetYByValue(lastLow); int y4 = chartScale.GetYByValue(lastClose); // Draw shadow line reuseVector1.X = x; reuseVector1.Y = y2; reuseVector2.X = x; reuseVector2.Y = y3; RenderTarget.DrawLine(reuseVector1, reuseVector2, dxmBrushes["shadowColor"].DxBrush); // Draw body if (lastClose == lastOpen) { // Draw horizontal line for doji reuseVector1.X = (x - barPaintWidth / 2); reuseVector1.Y = y1; reuseVector2.X = (x + barPaintWidth / 2); reuseVector2.Y = y1; RenderTarget.DrawLine(reuseVector1, reuseVector2, dxmBrushes["shadowColor"].DxBrush); } else { // Draw candlestick body if (lastClose > lastOpen) { UpdateRect(ref reuseRect, (x - barPaintWidth / 2), y4, barPaintWidth, (y1 - y4)); RenderTarget.FillRectangle(reuseRect, dxmBrushes["barColorUp"].DxBrush); } else { UpdateRect(ref reuseRect, (x - barPaintWidth / 2), y1, barPaintWidth, (y4 - y1)); RenderTarget.FillRectangle(reuseRect, dxmBrushes["barColorDown"].DxBrush); } // Draw border UpdateRect(ref reuseRect, ((x - barPaintWidth / 2) + (ShadowWidth / 2)), Math.Min(y4, y1), (barPaintWidth - ShadowWidth + 2), Math.Abs(y4 - y1)); RenderTarget.DrawRectangle(reuseRect, dxmBrushes["shadowColor"].DxBrush); } } public override void OnRenderTargetChanged() { try { foreach (KeyValuePair<string, DXMediaMap> item in dxmBrushes) { if (item.Value.DxBrush != null) item.Value.DxBrush.Dispose(); if (RenderTarget != null) item.Value.DxBrush = item.Value.MediaBrush.ToDxBrush(RenderTarget); } } catch (Exception exception) { Print($"MarginCandlestick OnRenderTargetChanged Error: {exception.Message}"); } } private void UpdateRect(ref SharpDX.RectangleF rectangle, float x, float y, float width, float height) { rectangle.X = x; rectangle.Y = y; rectangle.Width = width; rectangle.Height = height; } #region Properties [Browsable(false)] public class DXMediaMap { public SharpDX.Direct2D1.Brush DxBrush; public System.Windows.Media.Brush MediaBrush; } [NinjaScriptProperty] [Range(1, int.MaxValue)] [Display(Name="Period (Minutes)", Order=1, GroupName="Parameters")] public int Period { get; set; } [NinjaScriptProperty] [XmlIgnore] [Display(Name="BarColorDown", Order=2, GroupName="Parameters")] public Brush BarColorDown { get { return dxmBrushes["barColorDown"].MediaBrush; } set { dxmBrushes["barColorDown"].MediaBrush = value; } } [Browsable(false)] public string BarColorDownSerializable { get { return Serialize.BrushToString(BarColorDown); } set { BarColorDown = Serialize.StringToBrush(value); } } [NinjaScriptProperty] [XmlIgnore] [Display(Name="BarColorUp", Order=3, GroupName="Parameters")] public Brush BarColorUp { get { return dxmBrushes["barColorUp"].MediaBrush; } set { dxmBrushes["barColorUp"].MediaBrush = value; } } [Browsable(false)] public string BarColorUpSerializable { get { return Serialize.BrushToString(BarColorUp); } set { BarColorUp = Serialize.StringToBrush(value); } } [NinjaScriptProperty] [XmlIgnore] [Display(Name="ShadowColor", Order=4, GroupName="Parameters")] public Brush ShadowColor { get { return dxmBrushes["shadowColor"].MediaBrush; } set { dxmBrushes["shadowColor"].MediaBrush = value; } } [Browsable(false)] public string ShadowColorSerializable { get { return Serialize.BrushToString(ShadowColor); } set { ShadowColor = Serialize.StringToBrush(value); } } [NinjaScriptProperty] [Range(1, int.MaxValue)] [Display(Name="ShadowWidth", Order=5, GroupName="Parameters")] public int ShadowWidth { get; set; } #endregion } }​
Leave a comment:
-
Thanks! This is helpful.Originally posted by MiCe1999 View Post
Leave a comment:
-
Power of Three (PO3)
Hi everyone,
I am looking for a free / paid "Power of Three" (PO3) indicator that can be used with NT8.
It should be similar to the Trading View "HTF Power of Three" (by toodegrees) indicator which focuses on.
I would love to know if there is a "Power of Three" NT8 indicator out there OR worst-case scenario if it can be coded?
Many thanks,
Michel
Last edited by michelz; 02-18-2025, 08:33 AM.Tags: None
Latest Posts
Collapse
| Topics | Statistics | Last Post | ||
|---|---|---|---|---|
|
Started by Mindset, 04-21-2026, 06:46 AM
|
0 responses
78 views
0 likes
|
Last Post
by Mindset
04-21-2026, 06:46 AM
|
||
|
Started by M4ndoo, 04-20-2026, 05:21 PM
|
0 responses
109 views
0 likes
|
Last Post
by M4ndoo
04-20-2026, 05:21 PM
|
||
|
Started by M4ndoo, 04-19-2026, 05:54 PM
|
0 responses
57 views
0 likes
|
Last Post
by M4ndoo
04-19-2026, 05:54 PM
|
||
|
Started by cmoran13, 04-16-2026, 01:02 PM
|
0 responses
108 views
0 likes
|
Last Post
by cmoran13
04-16-2026, 01:02 PM
|
||
|
Started by PaulMohn, 04-10-2026, 11:11 AM
|
0 responses
65 views
0 likes
|
Last Post
by PaulMohn
04-10-2026, 11:11 AM
|

Leave a comment: