Candle Color Pressure by Naya
150 downloads / 73 views / Created: 19.06.2025 Average Rating: 0
Indicator Description
The Candle Color Pressure indicator measures the balance between bullish and bearish candles over a defined period to assess market sentiment. It counts the number of green (bullish) versus red (bearish) candles within the lookback period and converts these counts into percentages. A high percentage of bullish candles indicates strong buying pressure and potential upward momentum, while a high percentage of bearish candles suggests selling pressure and potential downward movement. The indicator includes various logic conditions such as percentage thresholds and crossover signals to generate trading signals. Doji candles (where open equals close) are tracked separately and not counted toward either bullish or bearish pressure. With customizable period settings (10-100 bars) and threshold percentages (10-100%), traders can adapt the indicator to different market conditions and timeframes for both entry and exit timing decisions.
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 CandleColorPressure : Indicator
{
public CandleColorPressure()
{
IndicatorName = "Candle Color Pressure";
PossibleSlots = SlotTypes.OpenFilter | SlotTypes.CloseFilter;
IndicatorAuthor = "NAYA,+237674724684";
IndicatorVersion = "1.0";
IndicatorDescription = "Analyzes the pressure between bullish and bearish candles 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[]
{
"Bullish count is above threshold",
"Bullish count is below threshold",
"Bullish count crosses above threshold",
"Bullish count crosses below threshold",
"Bearish count is above threshold",
"Bearish count is below threshold",
"Bearish count crosses above threshold",
"Bearish 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 candle color 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 candle color 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 candle color pressure percentages and previous values
double[] bullishPercent = new double[Bars];
double[] bearishPercent = new double[Bars];
double[] prevBullishPercent = new double[Bars];
double[] prevBearishPercent = new double[Bars];
// Calculate candle color pressure for each bar
for (int bar = firstBar; bar < Bars; bar++)
{
int bullishCount = 0;
int bearishCount = 0;
int doji = 0;
// Look back over the period
for (int i = 0; i < period; i++)
{
int currentBar = bar - i - previous;
if (currentBar < 0) continue;
if (Close[currentBar] > Open[currentBar])
bullishCount++;
else if (Close[currentBar] < Open[currentBar])
bearishCount++;
else
doji++; // Doji candles (open = close)
}
// Calculate percentages
bullishPercent[bar] = (double)bullishCount / period * 100;
bearishPercent[bar] = (double)bearishCount / period * 100;
// Store previous values for crossover detection
if (bar > firstBar)
{
prevBullishPercent[bar] = bullishPercent[bar - 1];
prevBearishPercent[bar] = bearishPercent[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 "Bullish count is above threshold":
for (int bar = firstBar; bar < Bars; bar++)
{
Component[0].Value[bar] = bullishPercent[bar] > threshold ? 1 : 0;
Component[1].Value[bar] = bearishPercent[bar] > threshold ? 1 : 0;
}
break;
case "Bullish count is below threshold":
for (int bar = firstBar; bar < Bars; bar++)
{
Component[0].Value[bar] = bullishPercent[bar] < threshold ? 1 : 0;
Component[1].Value[bar] = bearishPercent[bar] < threshold ? 1 : 0;
}
break;
case "Bullish count crosses above threshold":
for (int bar = firstBar; bar < Bars; bar++)
{
Component[0].Value[bar] = bullishPercent[bar] > threshold &&
prevBullishPercent[bar] <= threshold ? 1 : 0;
Component[1].Value[bar] = bearishPercent[bar] > threshold &&
prevBearishPercent[bar] <= threshold ? 1 : 0;
}
break;
case "Bullish count crosses below threshold":
for (int bar = firstBar; bar < Bars; bar++)
{
Component[0].Value[bar] = bullishPercent[bar] < threshold &&
prevBullishPercent[bar] >= threshold ? 1 : 0;
Component[1].Value[bar] = bearishPercent[bar] < threshold &&
prevBearishPercent[bar] >= threshold ? 1 : 0;
}
break;
case "Bearish count is above threshold":
for (int bar = firstBar; bar < Bars; bar++)
{
Component[0].Value[bar] = bearishPercent[bar] > threshold ? 1 : 0;
Component[1].Value[bar] = bullishPercent[bar] > threshold ? 1 : 0;
}
break;
case "Bearish count is below threshold":
for (int bar = firstBar; bar < Bars; bar++)
{
Component[0].Value[bar] = bearishPercent[bar] < threshold ? 1 : 0;
Component[1].Value[bar] = bullishPercent[bar] < threshold ? 1 : 0;
}
break;
case "Bearish count crosses above threshold":
for (int bar = firstBar; bar < Bars; bar++)
{
Component[0].Value[bar] = bearishPercent[bar] > threshold &&
prevBearishPercent[bar] <= threshold ? 1 : 0;
Component[1].Value[bar] = bullishPercent[bar] > threshold &&
prevBullishPercent[bar] <= threshold ? 1 : 0;
}
break;
case "Bearish count crosses below threshold":
for (int bar = firstBar; bar < Bars; bar++)
{
Component[0].Value[bar] = bearishPercent[bar] < threshold &&
prevBearishPercent[bar] >= threshold ? 1 : 0;
Component[1].Value[bar] = bullishPercent[bar] < threshold &&
prevBullishPercent[bar] >= threshold ? 1 : 0;
}
break;
}
}
public override void SetDescription()
{
switch (IndParam.ListParam[0].Text)
{
case "Bullish count is above threshold":
EntryFilterLongDescription = "bullish candle count is above " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
EntryFilterShortDescription = "bearish candle count is above " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
ExitFilterLongDescription = EntryFilterLongDescription;
ExitFilterShortDescription = EntryFilterShortDescription;
break;
case "Bullish count is below threshold":
EntryFilterLongDescription = "bullish candle count is below " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
EntryFilterShortDescription = "bearish candle count is below " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
ExitFilterLongDescription = EntryFilterLongDescription;
ExitFilterShortDescription = EntryFilterShortDescription;
break;
case "Bullish count crosses above threshold":
EntryFilterLongDescription = "bullish candle count crosses above " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
EntryFilterShortDescription = "bearish candle count crosses above " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
ExitFilterLongDescription = EntryFilterLongDescription;
ExitFilterShortDescription = EntryFilterShortDescription;
break;
case "Bullish count crosses below threshold":
EntryFilterLongDescription = "bullish candle count crosses below " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
EntryFilterShortDescription = "bearish candle count crosses below " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
ExitFilterLongDescription = EntryFilterLongDescription;
ExitFilterShortDescription = EntryFilterShortDescription;
break;
case "Bearish count is above threshold":
EntryFilterLongDescription = "bearish candle count is above " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
EntryFilterShortDescription = "bullish candle count is above " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
ExitFilterLongDescription = EntryFilterLongDescription;
ExitFilterShortDescription = EntryFilterShortDescription;
break;
case "Bearish count is below threshold":
EntryFilterLongDescription = "bearish candle count is below " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
EntryFilterShortDescription = "bullish candle count is below " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
ExitFilterLongDescription = EntryFilterLongDescription;
ExitFilterShortDescription = EntryFilterShortDescription;
break;
case "Bearish count crosses above threshold":
EntryFilterLongDescription = "bearish candle count crosses above " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
EntryFilterShortDescription = "bullish candle count crosses above " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
ExitFilterLongDescription = EntryFilterLongDescription;
ExitFilterShortDescription = EntryFilterShortDescription;
break;
case "Bearish count crosses below threshold":
EntryFilterLongDescription = "bearish candle count crosses below " + IndParam.NumParam[1].ValueToString + "% over " + IndParam.NumParam[0].ValueToString + " periods";
EntryFilterShortDescription = "bullish candle 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 CandleColorPressure : public Indicator { public: CandleColorPressure(SlotTypes slotType) { SlotType = slotType; IndicatorName = "Candle Color Pressure"; WarningMessage = ""; IsAllowLTF = true; ExecTime = ExecutionTime_DuringTheBar; IsSeparateChart = false; IsDiscreteValues = false; IsDefaultGroupAll = false; } virtual void Calculate(DataSet &dataSet); }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CandleColorPressure::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 candle color pressure percentages and previous values double bullishPercent[]; ArrayResize(bullishPercent, Data.Bars); ArrayInitialize(bullishPercent, 0); double bearishPercent[]; ArrayResize(bearishPercent, Data.Bars); ArrayInitialize(bearishPercent, 0); double prevBullishPercent[]; ArrayResize(prevBullishPercent, Data.Bars); ArrayInitialize(prevBullishPercent, 0); double prevBearishPercent[]; ArrayResize(prevBearishPercent, Data.Bars); ArrayInitialize(prevBearishPercent, 0); // Calculate candle color pressure for each bar for(int bar = firstBar; bar < Data.Bars; bar++) { int bullishCount = 0; int bearishCount = 0; int doji = 0; // Look back over the period for(int i = 0; i < period; i++) { int currentBar = bar - i - previous; if(currentBar < 0) continue; if(Data.Close[currentBar] > Data.Open[currentBar]) bullishCount++; else if(Data.Close[currentBar] < Data.Open[currentBar]) bearishCount++; else doji++; // Doji candles (open = close) } // Calculate percentages bullishPercent[bar] = (double)bullishCount / period * 100; bearishPercent[bar] = (double)bearishCount / period * 100; // Store previous values for crossover detection if(bar > firstBar) { prevBullishPercent[bar] = bullishPercent[bar - 1]; prevBearishPercent[bar] = bearishPercent[bar - 1]; } } // Initialize components ArrayResize(Component[0].Value, Data.Bars); ArrayResize(Component[1].Value, Data.Bars); Component[0].CompName = "Bullish Pressure"; Component[0].DataType = IndComponentType_IndicatorValue; Component[0].FirstBar = firstBar; ArrayCopy(Component[0].Value, bullishPercent); 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 == "Bullish count is above threshold") { for(int bar = firstBar; bar < Data.Bars; bar++) { Component[1].Value[bar] = bullishPercent[bar] > threshold ? 1 : 0; Component[2].Value[bar] = bearishPercent[bar] > threshold ? 1 : 0; } } else if(ListParam[0].Text == "Bullish count is below threshold") { for(int bar = firstBar; bar < Data.Bars; bar++) { Component[1].Value[bar] = bullishPercent[bar] < threshold ? 1 : 0; Component[2].Value[bar] = bearishPercent[bar] < threshold ? 1 : 0; } } else if(ListParam[0].Text == "Bullish count crosses above threshold") { for(int bar = firstBar; bar < Data.Bars; bar++) { Component[1].Value[bar] = bullishPercent[bar] > threshold && prevBullishPercent[bar] <= threshold ? 1 : 0; Component[2].Value[bar] = bearishPercent[bar] > threshold && prevBearishPercent[bar] <= threshold ? 1 : 0; } } else if(ListParam[0].Text == "Bullish count crosses below threshold") { for(int bar = firstBar; bar < Data.Bars; bar++) { Component[1].Value[bar] = bullishPercent[bar] < threshold && prevBullishPercent[bar] >= threshold ? 1 : 0; Component[2].Value[bar] = bearishPercent[bar] < threshold && prevBearishPercent[bar] >= threshold ? 1 : 0; } } else if(ListParam[0].Text == "Bearish count is above threshold") { for(int bar = firstBar; bar < Data.Bars; bar++) { Component[1].Value[bar] = bearishPercent[bar] > threshold ? 1 : 0; Component[2].Value[bar] = bullishPercent[bar] > threshold ? 1 : 0; } } else if(ListParam[0].Text == "Bearish count is below threshold") { for(int bar = firstBar; bar < Data.Bars; bar++) { Component[1].Value[bar] = bearishPercent[bar] < threshold ? 1 : 0; Component[2].Value[bar] = bullishPercent[bar] < threshold ? 1 : 0; } } else if(ListParam[0].Text == "Bearish count crosses above threshold") { for(int bar = firstBar; bar < Data.Bars; bar++) { Component[1].Value[bar] = bearishPercent[bar] > threshold && prevBearishPercent[bar] <= threshold ? 1 : 0; Component[2].Value[bar] = bullishPercent[bar] > threshold && prevBullishPercent[bar] <= threshold ? 1 : 0; } } else if(ListParam[0].Text == "Bearish count crosses below threshold") { for(int bar = firstBar; bar < Data.Bars; bar++) { Component[1].Value[bar] = bearishPercent[bar] < threshold && prevBearishPercent[bar] >= threshold ? 1 : 0; Component[2].Value[bar] = bullishPercent[bar] < threshold && prevBullishPercent[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.;