Candle Wick Pressure by Naya
146 downloads / 81 views / Created: 19.06.2025 Average Rating: 0
Indicator Description
The Candle Wick Pressure indicator analyzes the relationship between upper and lower candlestick wicks over a specified period to gauge market pressure. It counts how many candles have dominant lower wicks versus upper wicks within a lookback period and calculates the percentage for each type. Lower wick dominance typically indicates buying pressure as traders push prices higher from the lows, while upper wick dominance suggests selling pressure as prices get rejected from highs. The indicator offers multiple logic options including threshold crossovers and comparisons, making it useful for identifying potential trend reversals or continuation patterns. Traders can set custom periods (10-100 bars) and threshold percentages (10-100%) to fine-tune the sensitivity. This indicator works as both an entry and exit filter, helping traders time their positions based on wick pressure dynamics.
Comments
//==============================================================
// Forex Strategy Builder
// Copyright © Miroslav Popov. All rights reserved.
//==============================================================
// THIS CODE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE.
//==============================================================
using System;
using System.Drawing;
using ForexStrategyBuilder.Infrastructure.Entities;
using ForexStrategyBuilder.Infrastructure.Enums;
using ForexStrategyBuilder.Infrastructure.Interfaces;
namespace ForexStrategyBuilder.Indicators.Custom
{
public class CandleWickPressure : Indicator
{
public CandleWickPressure()
{
IndicatorName = "Candle Wick Pressure";
PossibleSlots = SlotTypes.OpenFilter | SlotTypes.CloseFilter;
IndicatorAuthor = "NAYA,+237674724684";
IndicatorVersion = "1.0";
IndicatorDescription = "Analyzes the pressure between upper and lower wicks over a specified period";
}
public override void Initialize(SlotTypes slotType)
{
SlotType = slotType;
// The ComboBox parameters
IndParam.ListParam[0].Caption = "Logic";
IndParam.ListParam[0].ItemList = new[]
{
"LowerWickPressure count is above threshold",
"LowerWickPressure count is below threshold",
"LowerWickPressure count crosses above threshold",
"LowerWickPressure count crosses below threshold",
"UpperWickPressure count is above threshold",
"UpperWickPressure count is below threshold",
"UpperWickPressure count crosses above threshold",
"UpperWickPressure count crosses below threshold"
};
IndParam.ListParam[0].Index = 0;
IndParam.ListParam[0].Text = IndParam.ListParam[0].ItemList[IndParam.ListParam[0].Index];
IndParam.ListParam[0].Enabled = true;
IndParam.ListParam[0].ToolTip = "Logic of application of the indicator";
// The NumericUpDown parameters
IndParam.NumParam[0].Caption = "Period";
IndParam.NumParam[0].Value = 60;
IndParam.NumParam[0].Min = 10;
IndParam.NumParam[0].Max = 200;
IndParam.NumParam[0].Enabled = true;
IndParam.NumParam[0].ToolTip = "The period for calculating wick pressure";
IndParam.NumParam[1].Caption = "Threshold (%)";
IndParam.NumParam[1].Value = 70;
IndParam.NumParam[1].Min = 10;
IndParam.NumParam[1].Max = 100;
IndParam.NumParam[1].Enabled = true;
IndParam.NumParam[1].ToolTip = "The threshold percentage for wick pressure";
// The CheckBox parameters
IndParam.CheckParam[0].Caption = "Use previous bar value";
IndParam.CheckParam[0].Enabled = true;
IndParam.CheckParam[0].ToolTip = "Use the indicator value from the previous bar";
}
public override void Calculate(IDataSet dataSet)
{
DataSet = dataSet;
// Reading the parameters
int period = (int)IndParam.NumParam[0].Value;
double threshold = IndParam.NumParam[1].Value;
int previous = IndParam.CheckParam[0].Checked ? 1 : 0;
int firstBar = period + previous;
// Arrays to store wick pressure percentages and previous values
double[] lowerWickPressurePercent = new double[Bars];
double[] upperWickPressurePercent = new double[Bars];
double[] prevLowerWickPressurePercent = new double[Bars];
double[] prevUpperWickPressurePercent = new double[Bars];
// Calculate wick pressure for each bar
for (int bar = firstBar; bar < Bars; bar++)
{
int lowerWickPressureCount = 0;
int upperWickPressureCount = 0;
// Look back over the period
for (int i = 0; i < period; i++)
{
int currentBar = bar - i - previous;
if (currentBar < 0) continue;
double lowerWick = Math.Min(Open[currentBar], Close[currentBar]) - Low[currentBar];
double upperWick = High[currentBar] - Math.Max(Open[currentBar], Close[currentBar]);
if (lowerWick > upperWick)
lowerWickPressureCount++;
else if (upperWick > lowerWick)
upperWickPressureCount++;
// If equal, neither counter is incremented
}
// Calculate percentages
lowerWickPressurePercent[bar] = (double)lowerWickPressureCount / period * 100;
upperWickPressurePercent[bar] = (double)upperWickPressureCount / period * 100;
// Store previous values for crossover detection
if (bar > firstBar)
{
prevLowerWickPressurePercent[bar] = lowerWickPressurePercent[bar - 1];
prevUpperWickPressurePercent[bar] = upperWickPressurePercent[bar - 1];
}
}
// Saving the components
Component = new IndicatorComp[2];
Component[0] = new IndicatorComp
{
ChartType = IndChartType.NoChart,
FirstBar = firstBar,
Value = new double[Bars]
};
Component[1] = new IndicatorComp
{
ChartType = IndChartType.NoChart,
FirstBar = firstBar,
Value = new double[Bars]
};
// Sets the Component's type
if (SlotType == SlotTypes.OpenFilter)
{
Component[0].DataType = IndComponentType.AllowOpenLong;
Component[0].CompName = "Is long entry allowed";
Component[1].DataType = IndComponentType.AllowOpenShort;
Component[1].CompName = "Is short entry allowed";
}
else if (SlotType == SlotTypes.CloseFilter)
{
Component[0].DataType = IndComponentType.ForceCloseLong;
Component[0].CompName = "Close out long position";
Component[1].DataType = IndComponentType.ForceCloseShort;
Component[1].CompName = "Close out short position";
}
// Apply logic based on selected option
switch (IndParam.ListParam[0].Text)
{
case "LowerWickPressure count is above threshold":
for (int bar = firstBar; bar < Bars; bar++)
{
Component[0].Value[bar] = lowerWickPressurePercent[bar] > threshold ? 1 : 0;
Component[1].Value[bar] = upperWickPressurePercent[bar] > threshold ? 1 : 0;
}
break;
case "LowerWickPressure count is below threshold":
for (int bar = firstBar; bar < Bars; bar++)
{
Component[0].Value[bar] = lowerWickPressurePercent[bar] < threshold ? 1 : 0;
Component[1].Value[bar] = upperWickPressurePercent[bar] < threshold ? 1 : 0;
}
break;
case "LowerWickPressure count crosses above threshold":
for (int bar = firstBar; bar < Bars; bar++)
{
Component[0].Value[bar] = lowerWickPressurePercent[bar] > threshold &&
prevLowerWickPressurePercent[bar] <= threshold ? 1 : 0;
Component[1].Value[bar] = upperWickPressurePercent[bar] > threshold &&
prevUpperWickPressurePercent[bar] <= threshold ? 1 : 0;
}
break;
case "LowerWickPressure count crosses below threshold":
for (int bar = firstBar; bar < Bars; bar++)
{
Component[0].Value[bar] = lowerWickPressurePercent[bar] < threshold &&
prevLowerWickPressurePercent[bar] >= threshold ? 1 : 0;
Component[1].Value[bar] = upperWickPressurePercent[bar] < threshold &&
prevUpperWickPressurePercent[bar] >= threshold ? 1 : 0;
}
break;
case "UpperWickPressure count is above threshold":
for (int bar = firstBar; bar < Bars; bar++)
{
Component[0].Value[bar] = upperWickPressurePercent[bar] > threshold ? 1 : 0;
Component[1].Value[bar] = lowerWickPressurePercent[bar] > threshold ? 1 : 0;
}
break;
case "UpperWickPressure count is below threshold":
for (int bar = firstBar; bar < Bars; bar++)
{
Component[0].Value[bar] = upperWickPressurePercent[bar] < threshold ? 1 : 0;
Component[1].Value[bar] = lowerWickPressurePercent[bar] < threshold ? 1 : 0;
}
break;
case "UpperWickPressure count crosses above threshold":
for (int bar = firstBar; bar < Bars; bar++)
{
Component[0].Value[bar] = upperWickPressurePercent[bar] > threshold &&
prevUpperWickPressurePercent[bar] <= threshold ? 1 : 0;
Component[1].Value[bar] = lowerWickPressurePercent[bar] > threshold &&
prevLowerWickPressurePercent[bar] <= threshold ? 1 : 0;
}
break;
case "UpperWickPressure count crosses below threshold":
for (int bar = firstBar; bar < Bars; bar++)
{
Component[0].Value[bar] = upperWickPressurePercent[bar] < threshold &&
prevUpperWickPressurePercent[bar] >= threshold ? 1 : 0;
Component[1].Value[bar] = lowerWickPressurePercent[bar] < threshold &&
prevLowerWickPressurePercent[bar] >= threshold ? 1 : 0;
}
break;
}
}
public override void SetDescription()
{
switch (IndParam.ListParam[0].Text)
{
case "LowerWickPressure count is above threshold":
EntryFilterLongDescription = "lower wick pressure count is above " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
EntryFilterShortDescription = "upper wick pressure count is above " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
ExitFilterLongDescription = EntryFilterLongDescription;
ExitFilterShortDescription = EntryFilterShortDescription;
break;
case "LowerWickPressure count is below threshold":
EntryFilterLongDescription = "lower wick pressure count is below " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
EntryFilterShortDescription = "upper wick pressure count is below " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
ExitFilterLongDescription = EntryFilterLongDescription;
ExitFilterShortDescription = EntryFilterShortDescription;
break;
case "LowerWickPressure count crosses above threshold":
EntryFilterLongDescription = "lower wick pressure count crosses above " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
EntryFilterShortDescription = "upper wick pressure count crosses above " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
ExitFilterLongDescription = EntryFilterLongDescription;
ExitFilterShortDescription = EntryFilterShortDescription;
break;
case "LowerWickPressure count crosses below threshold":
EntryFilterLongDescription = "lower wick pressure count crosses below " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
EntryFilterShortDescription = "upper wick pressure count crosses below " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
ExitFilterLongDescription = EntryFilterLongDescription;
ExitFilterShortDescription = EntryFilterShortDescription;
break;
case "UpperWickPressure count is above threshold":
EntryFilterLongDescription = "upper wick pressure count is above " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
EntryFilterShortDescription = "lower wick pressure count is above " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
ExitFilterLongDescription = EntryFilterLongDescription;
ExitFilterShortDescription = EntryFilterShortDescription;
break;
case "UpperWickPressure count is below threshold":
EntryFilterLongDescription = "upper wick pressure count is below " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
EntryFilterShortDescription = "lower wick pressure count is below " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
ExitFilterLongDescription = EntryFilterLongDescription;
ExitFilterShortDescription = EntryFilterShortDescription;
break;
case "UpperWickPressure count crosses above threshold":
EntryFilterLongDescription = "upper wick pressure count crosses above " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
EntryFilterShortDescription = "lower wick pressure count crosses above " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
ExitFilterLongDescription = EntryFilterLongDescription;
ExitFilterShortDescription = EntryFilterShortDescription;
break;
case "UpperWickPressure count crosses below threshold":
EntryFilterLongDescription = "upper wick pressure count crosses below " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
EntryFilterShortDescription = "lower wick pressure count crosses below " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
ExitFilterLongDescription = EntryFilterLongDescription;
ExitFilterShortDescription = EntryFilterShortDescription;
break;
}
}
public override string ToString()
{
return string.Format("{0}{1} ({2}, {3})",
IndicatorName,
IndParam.CheckParam[0].Checked ? "*" : "",
IndParam.NumParam[0].ValueToString,
IndParam.NumParam[1].ValueToString);
}
}
}
//+--------------------------------------------------------------------+ //| Copyright: (C) 2025 NAYA. | //| Website: http://forexsb.com/ | //| Support: http://forexsb.com/forum/ | //| License: Proprietary under the following circumstances: | //| | //| This code is a part of Forex Strategy Builder. It is free for | //| use as an integral part of Forex Strategy Builder. | //| One can modify it in order to improve the code or to fit it for | //| personal use. This code or any part of it cannot be used in | //| other applications without a permission. | //| The contact information cannot be changed. | //| | //| NO LIABILITY FOR CONSEQUENTIAL DAMAGES | //| | //| In no event shall the author be liable for any damages whatsoever | //| (including, without limitation, incidental, direct, indirect and | //| consequential damages, damages for loss of business profits, | //| business interruption, loss of business information, or other | //| pecuniary loss) arising out of the use or inability to use this | //| product, even if advised of the possibility of such damages. | //+--------------------------------------------------------------------+ #property copyright "NAYA 2025." #property link "NAYA +237674724684" #property version "1.0" #property strict #include <Forexsb.com/Indicator.mqh> #include <Forexsb.com/Enumerations.mqh> //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CandleWickPressure : public Indicator { public: CandleWickPressure(SlotTypes slotType) { SlotType = slotType; IndicatorName = "Candle Wick Pressure"; WarningMessage = ""; IsAllowLTF = true; ExecTime = ExecutionTime_DuringTheBar; IsSeparateChart = false; IsDiscreteValues = false; IsDefaultGroupAll = false; } virtual void Calculate(DataSet &dataSet); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CandleWickPressure::Calculate(DataSet &dataSet) { Data = GetPointer(dataSet); int period = (int)NumParam[0].Value; double threshold = NumParam[1].Value; int previous = CheckParam[0].Checked ? 1 : 0; int firstBar = period + previous; // Arrays to store wick pressure percentages and previous values double lowerWickPressurePercent[]; ArrayResize(lowerWickPressurePercent, Data.Bars); ArrayInitialize(lowerWickPressurePercent, 0); double upperWickPressurePercent[]; ArrayResize(upperWickPressurePercent, Data.Bars); ArrayInitialize(upperWickPressurePercent, 0); double prevLowerWickPressurePercent[]; ArrayResize(prevLowerWickPressurePercent, Data.Bars); ArrayInitialize(prevLowerWickPressurePercent, 0); double prevUpperWickPressurePercent[]; ArrayResize(prevUpperWickPressurePercent, Data.Bars); ArrayInitialize(prevUpperWickPressurePercent, 0); // Calculate wick pressure for each bar for(int bar = firstBar; bar < Data.Bars; bar++) { int lowerWickPressureCount = 0; int upperWickPressureCount = 0; // Look back over the period for(int i = 0; i < period; i++) { int currentBar = bar - i - previous; if(currentBar < 0) continue; double lowerWick = MathMin(Data.Open[currentBar], Data.Close[currentBar]) - Data.Low[currentBar]; double upperWick = Data.High[currentBar] - MathMax(Data.Open[currentBar], Data.Close[currentBar]); if(lowerWick > upperWick) lowerWickPressureCount++; else if(upperWick > lowerWick) upperWickPressureCount++; // If equal, neither counter is incremented } // Calculate percentages lowerWickPressurePercent[bar] = (double)lowerWickPressureCount / period * 100; upperWickPressurePercent[bar] = (double)upperWickPressureCount / period * 100; // Store previous values for crossover detection if(bar > firstBar) { prevLowerWickPressurePercent[bar] = lowerWickPressurePercent[bar - 1]; prevUpperWickPressurePercent[bar] = upperWickPressurePercent[bar - 1]; } } // Initialize components ArrayResize(Component[0].Value, Data.Bars); ArrayResize(Component[1].Value, Data.Bars); Component[0].CompName = "Lower Wick Pressure"; Component[0].DataType = IndComponentType_IndicatorValue; Component[0].FirstBar = firstBar; ArrayCopy(Component[0].Value, lowerWickPressurePercent); if(SlotType == SlotTypes_OpenFilter) { Component[1].DataType = IndComponentType_AllowOpenLong; Component[1].CompName = "Is long entry allowed"; Component[2].DataType = IndComponentType_AllowOpenShort; Component[2].CompName = "Is short entry allowed"; ArrayResize(Component[2].Value, Data.Bars); Component[1].FirstBar = firstBar; Component[2].FirstBar = firstBar; ArrayInitialize(Component[1].Value, 0); ArrayInitialize(Component[2].Value, 0); } else if(SlotType == SlotTypes_CloseFilter) { Component[1].DataType = IndComponentType_ForceCloseLong; Component[1].CompName = "Close out long position"; Component[2].DataType = IndComponentType_ForceCloseShort; Component[2].CompName = "Close out short position"; ArrayResize(Component[2].Value, Data.Bars); Component[1].FirstBar = firstBar; Component[2].FirstBar = firstBar; ArrayInitialize(Component[1].Value, 0); ArrayInitialize(Component[2].Value, 0); } // Apply logic based on selected option if(ListParam[0].Text == "LowerWickPressure count is above threshold") { for(int bar = firstBar; bar < Data.Bars; bar++) { Component[1].Value[bar] = lowerWickPressurePercent[bar] > threshold ? 1 : 0; Component[2].Value[bar] = upperWickPressurePercent[bar] > threshold ? 1 : 0; } } else if(ListParam[0].Text == "LowerWickPressure count is below threshold") { for(int bar = firstBar; bar < Data.Bars; bar++) { Component[1].Value[bar] = lowerWickPressurePercent[bar] < threshold ? 1 : 0; Component[2].Value[bar] = upperWickPressurePercent[bar] < threshold ? 1 : 0; } } else if(ListParam[0].Text == "LowerWickPressure count crosses above threshold") { for(int bar = firstBar; bar < Data.Bars; bar++) { Component[1].Value[bar] = lowerWickPressurePercent[bar] > threshold && prevLowerWickPressurePercent[bar] <= threshold ? 1 : 0; Component[2].Value[bar] = upperWickPressurePercent[bar] > threshold && prevUpperWickPressurePercent[bar] <= threshold ? 1 : 0; } } else if(ListParam[0].Text == "LowerWickPressure count crosses below threshold") { for(int bar = firstBar; bar < Data.Bars; bar++) { Component[1].Value[bar] = lowerWickPressurePercent[bar] < threshold && prevLowerWickPressurePercent[bar] >= threshold ? 1 : 0; Component[2].Value[bar] = upperWickPressurePercent[bar] < threshold && prevUpperWickPressurePercent[bar] >= threshold ? 1 : 0; } } else if(ListParam[0].Text == "UpperWickPressure count is above threshold") { for(int bar = firstBar; bar < Data.Bars; bar++) { Component[1].Value[bar] = upperWickPressurePercent[bar] > threshold ? 1 : 0; Component[2].Value[bar] = lowerWickPressurePercent[bar] > threshold ? 1 : 0; } } else if(ListParam[0].Text == "UpperWickPressure count is below threshold") { for(int bar = firstBar; bar < Data.Bars; bar++) { Component[1].Value[bar] = upperWickPressurePercent[bar] < threshold ? 1 : 0; Component[2].Value[bar] = lowerWickPressurePercent[bar] < threshold ? 1 : 0; } } else if(ListParam[0].Text == "UpperWickPressure count crosses above threshold") { for(int bar = firstBar; bar < Data.Bars; bar++) { Component[1].Value[bar] = upperWickPressurePercent[bar] > threshold && prevUpperWickPressurePercent[bar] <= threshold ? 1 : 0; Component[2].Value[bar] = lowerWickPressurePercent[bar] > threshold && prevLowerWickPressurePercent[bar] <= threshold ? 1 : 0; } } else if(ListParam[0].Text == "UpperWickPressure count crosses below threshold") { for(int bar = firstBar; bar < Data.Bars; bar++) { Component[1].Value[bar] = upperWickPressurePercent[bar] < threshold && prevUpperWickPressurePercent[bar] >= threshold ? 1 : 0; Component[2].Value[bar] = lowerWickPressurePercent[bar] < threshold && prevLowerWickPressurePercent[bar] >= threshold ? 1 : 0; } } } //+------------------------------------------------------------------+
Risk warning: Forex, spread bets and CFD are leveraged products. They may not be suitable for you as they carry a high degree of risk to your capital and you can lose more than your initial investment. You should ensure you understand all of the risks.
Copyright © 2006 - 2025, Forex Software Ltd.;
Copyright © 2006 - 2025, Forex Software Ltd.;