Skip to content

Commit 9ededde

Browse files
committed
fix on volume profile calculations
1 parent 382003d commit 9ededde

File tree

1 file changed

+113
-51
lines changed

1 file changed

+113
-51
lines changed

Indicators/FreeOrderFlow/FofVolumeProfile.cs

Lines changed: 113 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -40,31 +40,31 @@ protected override void OnStateChange()
4040
{
4141
if (State == State.SetDefaults)
4242
{
43-
Description = @"Free Order Flow Volume Profile";
44-
Name = "Volume Profile";
45-
IsChartOnly = true;
46-
IsOverlay = true;
47-
DisplayInDataBox = false;
48-
DrawOnPricePanel = true;
43+
Description = @"Free Order Flow Volume Profile";
44+
Name = "Volume Profile";
45+
IsChartOnly = true;
46+
IsOverlay = true;
47+
DisplayInDataBox = false;
48+
DrawOnPricePanel = true;
4949

5050
// Setup
51-
DisplayMode = FofVolumeProfileMode.Standard;
52-
ResolutionMode = FofVolumeProfileResolution.Tick;
53-
Resolution = 1;
54-
ValueArea = 70;
55-
DisplayTotal = true;
51+
DisplayMode = FofVolumeProfileMode.Standard;
52+
ResolutionMode = FofVolumeProfileResolution.Tick;
53+
Resolution = 1;
54+
ValueArea = 70;
55+
DisplayTotal = true;
5656

5757
// Visual
58-
Width = 60;
59-
Opacity = 40;
60-
ValueAreaOpacity = 80;
61-
ShowPoc = true;
62-
ShowValueArea = true;
63-
VolumeBrush = Brushes.CornflowerBlue;
64-
BuyBrush = Brushes.DarkCyan;
65-
SellBrush = Brushes.MediumVioletRed;
66-
PocStroke = new Stroke(Brushes.Goldenrod, 1);
67-
ValueAreaStroke = new Stroke(Brushes.CornflowerBlue, DashStyleHelper.Dash, 1);
58+
Width = 60;
59+
Opacity = 40;
60+
ValueAreaOpacity = 80;
61+
ShowPoc = true;
62+
ShowValueArea = true;
63+
VolumeBrush = Brushes.CornflowerBlue;
64+
BuyBrush = Brushes.DarkCyan;
65+
SellBrush = Brushes.MediumVioletRed;
66+
PocStroke = new Stroke(Brushes.Goldenrod, 1);
67+
ValueAreaStroke = new Stroke(Brushes.CornflowerBlue, DashStyleHelper.Dash, 1);
6868
}
6969
else if (State == State.Configure)
7070
{
@@ -88,50 +88,53 @@ protected override void OnStateChange()
8888
#region Calculations
8989
protected override void OnBarUpdate()
9090
{
91-
if(BarsInProgress == 1)
91+
if (BarsInProgress == 1)
9292
{
9393
long buyVolume, sellVolume, otherVolume;
9494

95-
if(ResolutionMode == FofVolumeProfileResolution.Tick && Resolution == 1)
95+
if (ResolutionMode == FofVolumeProfileResolution.Tick && Resolution == 1)
9696
{
9797
// 1 tick uses bid and ask price
9898
var ask = BarsArray[1].GetAsk(CurrentBar);
9999
var bid = BarsArray[1].GetBid(CurrentBar);
100100

101-
buyVolume = (Closes[1][0] >= ask) ? (long) Volumes[1][0] : 0;
102-
sellVolume = (Closes[1][0] <= bid) ? (long) Volumes[1][0] : 0;
101+
buyVolume = (Closes[1][0] >= ask) ? (long)Volumes[1][0] : 0;
102+
sellVolume = (Closes[1][0] <= bid) ? (long)Volumes[1][0] : 0;
103103
otherVolume = (Closes[1][0] < ask && Closes[1][0] > bid) ? (long)Volumes[1][0] : 0;
104104
}
105105
else
106106
{
107-
buyVolume = Closes[1][0] > Opens[1][0] ? (long) Volumes[1][0] : 0;
108-
sellVolume = Closes[1][0] < Opens[1][0] ? (long) Volumes[1][0] : 0;
107+
buyVolume = Closes[1][0] > Opens[1][0] ? (long)Volumes[1][0] : 0;
108+
sellVolume = Closes[1][0] < Opens[1][0] ? (long)Volumes[1][0] : 0;
109109
otherVolume = 0;
110110
}
111111

112-
if(Profiles.Count > 0)
112+
if (Profiles.Count > 0)
113113
{
114114
var profile = Profiles.Last();
115115
profile.UpdateRow(Closes[1][0], buyVolume, sellVolume, otherVolume);
116116
}
117117
}
118118
else // BarsInProgress == 0
119119
{
120-
if(State == State.Realtime || IsFirstTickOfBar) {
120+
if (State == State.Realtime || IsFirstTickOfBar)
121+
{
121122
Profiles.Last().CalculateValueArea(ValueArea / 100f);
122123
}
123124

124-
if(CurrentBar == LastBar) return;
125+
if (CurrentBar == LastBar) return;
125126
LastBar = CurrentBar;
126127

127128
Profiles.Last().EndBar = CurrentBar;
128129

129-
if(
130+
if (
131+
IsFirstTickOfBar &&
130132
Period == FofVolumeProfilePeriod.Bars ||
131133
(Period == FofVolumeProfilePeriod.Sessions && Bars.IsFirstBarOfSession)
132134
)
133135
{
134-
if(State != State.Realtime) {
136+
if (State != State.Realtime)
137+
{
135138
Profiles.Last().CalculateValueArea(ValueArea / 100f);
136139
}
137140
Profiles.Add(new FofVolumeProfileData() { StartBar = CurrentBar });
@@ -162,32 +165,34 @@ protected override void OnRender(ChartControl chartControl, ChartScale chartScal
162165
(profile.StartBar < ChartBars.FromIndex && profile.EndBar < ChartBars.FromIndex) ||
163166
(profile.StartBar > ChartBars.ToIndex && profile.EndBar > ChartBars.ToIndex)
164167
) continue;
165-
if(DisplayMode == FofVolumeProfileMode.BuySell)
168+
if (DisplayMode == FofVolumeProfileMode.BuySell)
166169
{
167170
volProfileRenderer.RenderBuySellProfile(profile, buyBrushDX, sellBrushDX);
168171
}
169172
else
170173
{
171174
volProfileRenderer.RenderProfile(profile, volumeBrushDX);
172175
}
173-
if(ShowPoc) volProfileRenderer.RenderPoc(profile, PocStroke.BrushDX, PocStroke.Width, PocStroke.StrokeStyle, DisplayTotal);
174-
if(ShowValueArea) volProfileRenderer.RenderValueArea(profile, ValueAreaStroke.BrushDX, ValueAreaStroke.Width, ValueAreaStroke.StrokeStyle, DisplayTotal);
175-
if(DisplayMode == FofVolumeProfileMode.Delta)
176+
if (ShowPoc) volProfileRenderer.RenderPoc(profile, PocStroke.BrushDX, PocStroke.Width, PocStroke.StrokeStyle, DisplayTotal);
177+
if (ShowValueArea) volProfileRenderer.RenderValueArea(profile, ValueAreaStroke.BrushDX, ValueAreaStroke.Width, ValueAreaStroke.StrokeStyle, DisplayTotal);
178+
if (DisplayMode == FofVolumeProfileMode.Delta)
176179
{
177180
volProfileRenderer.RenderDeltaProfile(profile, buyBrushDX, sellBrushDX);
178181
}
179-
if(DisplayTotal) {
182+
if (DisplayTotal)
183+
{
180184
volProfileRenderer.RenderTotalVolume(profile, totalTextBrushDX);
181185
}
182186
}
183187
}
184188

185189
public override void OnRenderTargetChanged()
186190
{
187-
if(volumeBrushDX != null) volumeBrushDX.Dispose();
188-
if(buyBrushDX != null) buyBrushDX.Dispose();
189-
if(sellBrushDX != null) sellBrushDX.Dispose();
190-
if (RenderTarget != null) {
191+
if (volumeBrushDX != null) volumeBrushDX.Dispose();
192+
if (buyBrushDX != null) buyBrushDX.Dispose();
193+
if (sellBrushDX != null) sellBrushDX.Dispose();
194+
if (RenderTarget != null)
195+
{
191196
volumeBrushDX = VolumeBrush.ToDxBrush(RenderTarget);
192197
buyBrushDX = BuyBrush.ToDxBrush(RenderTarget);
193198
sellBrushDX = SellBrush.ToDxBrush(RenderTarget);
@@ -199,44 +204,44 @@ public override void OnRenderTargetChanged()
199204

200205
#region Properties
201206
// Setup
202-
[Display(Name = "Display mode", Description="Profile mode to render", Order = 1, GroupName = "Setup")]
207+
[Display(Name = "Display mode", Description = "Profile mode to render", Order = 1, GroupName = "Setup")]
203208
public FofVolumeProfileMode DisplayMode { get; set; }
204209

205210
[NinjaScriptProperty]
206-
[Display(Name = "Profile Period", Description="Calculate profile from region", Order = 1, GroupName = "Setup")]
211+
[Display(Name = "Profile Period", Description = "Calculate profile from region", Order = 1, GroupName = "Setup")]
207212
public FofVolumeProfilePeriod Period { get; set; }
208213

209214
[NinjaScriptProperty]
210-
[Display(Name = "Resolution Mode", Description="Calculate profile from region", Order = 2, GroupName = "Setup")]
215+
[Display(Name = "Resolution Mode", Description = "Calculate profile from region", Order = 2, GroupName = "Setup")]
211216
public FofVolumeProfileResolution ResolutionMode { get; set; }
212217

213218
[NinjaScriptProperty]
214-
[Display(Name = "Resolution", Description="Calculate profile from region", Order = 3, GroupName = "Setup")]
219+
[Display(Name = "Resolution", Description = "Calculate profile from region", Order = 3, GroupName = "Setup")]
215220
public int Resolution { get; set; }
216221

217222
[Range(10, 90)]
218-
[Display(Name = "Value Area (%)", Description="Value area percentage", Order = 7, GroupName = "Setup")]
223+
[Display(Name = "Value Area (%)", Description = "Value area percentage", Order = 7, GroupName = "Setup")]
219224
public int ValueArea { get; set; }
220225

221226
[Display(Name = "Display Total Volume", Order = 8, GroupName = "Setup")]
222227
public bool DisplayTotal { get; set; }
223228

224229
// Visual
225-
[Display(Name = "Profile width (%)", Description="Width of bars relative to range", Order = 1, GroupName = "Visual")]
230+
[Display(Name = "Profile width (%)", Description = "Width of bars relative to range", Order = 1, GroupName = "Visual")]
226231
public int Width { get; set; }
227232

228233
[Range(1, 100)]
229-
[Display(Name = "Profile opacity (%)", Description="Opacity of bars out value area", Order = 2, GroupName = "Visual")]
234+
[Display(Name = "Profile opacity (%)", Description = "Opacity of bars out value area", Order = 2, GroupName = "Visual")]
230235
public int Opacity { get; set; }
231236

232237
[Range(1, 100)]
233-
[Display(Name = "Value area opacity (%)", Description="Opacity of bars in value area", Order = 2, GroupName = "Visual")]
238+
[Display(Name = "Value area opacity (%)", Description = "Opacity of bars in value area", Order = 2, GroupName = "Visual")]
234239
public int ValueAreaOpacity { get; set; }
235240

236-
[Display(Name = "Show POC", Description="Show PoC line", Order = 5, GroupName = "Setup")]
241+
[Display(Name = "Show POC", Description = "Show PoC line", Order = 5, GroupName = "Setup")]
237242
public bool ShowPoc { get; set; }
238243

239-
[Display(Name = "Show Value Area", Description="Show value area high and low lines", Order = 6, GroupName = "Setup")]
244+
[Display(Name = "Show Value Area", Description = "Show value area high and low lines", Order = 6, GroupName = "Setup")]
240245
public bool ShowValueArea { get; set; }
241246

242247
[XmlIgnore]
@@ -281,3 +286,60 @@ public string SellBrushSerialize
281286
#endregion
282287
}
283288
}
289+
290+
#region NinjaScript generated code. Neither change nor remove.
291+
292+
namespace NinjaTrader.NinjaScript.Indicators
293+
{
294+
public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase
295+
{
296+
private FreeOrderFlow.FofVolumeProfile[] cacheFofVolumeProfile;
297+
public FreeOrderFlow.FofVolumeProfile FofVolumeProfile(FofVolumeProfilePeriod period, FofVolumeProfileResolution resolutionMode, int resolution)
298+
{
299+
return FofVolumeProfile(Input, period, resolutionMode, resolution);
300+
}
301+
302+
public FreeOrderFlow.FofVolumeProfile FofVolumeProfile(ISeries<double> input, FofVolumeProfilePeriod period, FofVolumeProfileResolution resolutionMode, int resolution)
303+
{
304+
if (cacheFofVolumeProfile != null)
305+
for (int idx = 0; idx < cacheFofVolumeProfile.Length; idx++)
306+
if (cacheFofVolumeProfile[idx] != null && cacheFofVolumeProfile[idx].Period == period && cacheFofVolumeProfile[idx].ResolutionMode == resolutionMode && cacheFofVolumeProfile[idx].Resolution == resolution && cacheFofVolumeProfile[idx].EqualsInput(input))
307+
return cacheFofVolumeProfile[idx];
308+
return CacheIndicator<FreeOrderFlow.FofVolumeProfile>(new FreeOrderFlow.FofVolumeProfile(){ Period = period, ResolutionMode = resolutionMode, Resolution = resolution }, input, ref cacheFofVolumeProfile);
309+
}
310+
}
311+
}
312+
313+
namespace NinjaTrader.NinjaScript.MarketAnalyzerColumns
314+
{
315+
public partial class MarketAnalyzerColumn : MarketAnalyzerColumnBase
316+
{
317+
public Indicators.FreeOrderFlow.FofVolumeProfile FofVolumeProfile(FofVolumeProfilePeriod period, FofVolumeProfileResolution resolutionMode, int resolution)
318+
{
319+
return indicator.FofVolumeProfile(Input, period, resolutionMode, resolution);
320+
}
321+
322+
public Indicators.FreeOrderFlow.FofVolumeProfile FofVolumeProfile(ISeries<double> input , FofVolumeProfilePeriod period, FofVolumeProfileResolution resolutionMode, int resolution)
323+
{
324+
return indicator.FofVolumeProfile(input, period, resolutionMode, resolution);
325+
}
326+
}
327+
}
328+
329+
namespace NinjaTrader.NinjaScript.Strategies
330+
{
331+
public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase
332+
{
333+
public Indicators.FreeOrderFlow.FofVolumeProfile FofVolumeProfile(FofVolumeProfilePeriod period, FofVolumeProfileResolution resolutionMode, int resolution)
334+
{
335+
return indicator.FofVolumeProfile(Input, period, resolutionMode, resolution);
336+
}
337+
338+
public Indicators.FreeOrderFlow.FofVolumeProfile FofVolumeProfile(ISeries<double> input , FofVolumeProfilePeriod period, FofVolumeProfileResolution resolutionMode, int resolution)
339+
{
340+
return indicator.FofVolumeProfile(input, period, resolutionMode, resolution);
341+
}
342+
}
343+
}
344+
345+
#endregion

0 commit comments

Comments
 (0)