Login Page - Create Account

Support Board


Date/Time: Tue, 26 Aug 2025 10:09:00 +0000



Post From: Value Area High/Low

[2025-07-24 13:17:00]
User781731 - Posts: 70
Thanks so much for your reply! It is exactly the same as the built-in study now. I'm not a programmer and use ChatGPT for this, so I really appreciate it.

The only issue is the script appears to be causing the chart to freeze. Do you know why this might be happening and what I can do to fix this issue?

#include "sierrachart.h"

SCDLLName("A-VAHL")

// Constants
const float VALUE_AREA_PERCENTAGE = 0.70f;

SCSFExport scsf_A_VAHL(SCStudyInterfaceRef sc)
{
SCSubgraphRef VAH = sc.Subgraph[0];
SCSubgraphRef VAL = sc.Subgraph[1];

if (sc.SetDefaults)
{
sc.GraphName = "A-VAHL";
sc.AutoLoop = 1;
sc.GraphRegion = 0;

VAH.Name = "Value Area High";
VAH.DrawStyle = DRAWSTYLE_STAIR_STEP;
VAH.PrimaryColor = RGB(40, 164, 40);
VAH.LineWidth = 1;

VAL.Name = "Value Area Low";
VAL.DrawStyle = DRAWSTYLE_STAIR_STEP;
VAL.PrimaryColor = RGB(255, 0, 0);
VAL.LineWidth = 1;

sc.ValueFormat = VALUEFORMAT_INHERITED;
sc.UpdateAlways = 1;
sc.MaintainVolumeAtPriceData = 1;

return;
}

// --- Session-persistent storage ---
static std::map<float, float> sessionVolumeMap; // price -> cumulative volume for session
static float sessionTotalVolume = 0.0f;
static SCDateTime lastSessionStart = 0;

SCDateTime currentDT = sc.BaseDateTimeIn[sc.Index];
SCDateTime sessionStart = sc.GetTradingDayStartDateTimeOfBar(currentDT);

// Reset at new session
if (sessionStart != lastSessionStart)
{
sessionVolumeMap.clear();
sessionTotalVolume = 0.0f;
lastSessionStart = sessionStart;
}

// Aggregate VAP data for all bars in session up to and including current bar
sessionVolumeMap.clear();
sessionTotalVolume = 0.0f;
for (int i = 0; i <= sc.Index; ++i)
{
SCDateTime barDT = sc.BaseDateTimeIn[i];
SCDateTime barSessionStart = sc.GetTradingDayStartDateTimeOfBar(barDT);
if (barSessionStart != sessionStart)
continue; // skip bars from previous sessions

int numLevels = sc.VolumeAtPriceForBars->GetSizeAtBarIndex(i);
const s_VolumeAtPriceV2* pVAP = nullptr;
for (int j = 0; j < numLevels; ++j)
{
if (!sc.VolumeAtPriceForBars->GetVAPElementAtIndex(i, j, &pVAP) || !pVAP)
continue;
float price = pVAP->PriceInTicks * sc.TickSize;
float vol = static_cast<float>(pVAP->Volume);
sessionVolumeMap[price] += vol;
sessionTotalVolume += vol;
}
}

if (sessionVolumeMap.empty() || sessionTotalVolume == 0.0f)
return;

// Build sorted list of (price, volume)
std::vector<std::pair<float, float>> sortedV;
sortedV.reserve(sessionVolumeMap.size());
for (const auto& e : sessionVolumeMap)
sortedV.emplace_back(e.first, e.second);
std::sort(sortedV.begin(), sortedV.end(), [](auto &a, auto &b){ return a.first < b.first; });

float targetVol = sessionTotalVolume * VALUE_AREA_PERCENTAGE;

// 1) Find POC
int pocIndex = 0;
float pocVol = sortedV[0].second;
for (int i = 1; i < (int)sortedV.size(); ++i)
{
if (sortedV[i].second > pocVol)
{
pocVol = sortedV[i].second;
pocIndex = i;
}
}

// 2) POC-centric expansion:
float cumVol = pocVol;
float bestVAL = sortedV[pocIndex].first;
float bestVAH = sortedV[pocIndex].first;
int left = pocIndex - 1;
int right = pocIndex + 1;

while (cumVol < targetVol && (left >= 0 || right < (int)sortedV.size()))
{
float leftVol = (left >= 0 ? sortedV[left].second : 0.0f);
float rightVol = (right < (int)sortedV.size() ? sortedV[right].second : 0.0f);

// --- equal-volume case: include both simultaneously ---
if (left >= 0 && right < (int)sortedV.size() && leftVol == rightVol)
{
cumVol += leftVol + rightVol;
bestVAL = sortedV[left].first;
bestVAH = sortedV[right].first;
--left; ++right;
}
// only left side remains
else if (right >= (int)sortedV.size())
{
cumVol += leftVol;
bestVAL = sortedV[left].first;
--left;
}
// only right side remains
else if (left < 0)
{
cumVol += rightVol;
bestVAH = sortedV[right].first;
++right;
}
// pick the side with greater volume
else if (leftVol > rightVol)
{
cumVol += leftVol;
bestVAL = sortedV[left].first;
--left;
}
else
{
cumVol += rightVol;
bestVAH = sortedV[right].first;
++right;
}
}

VAH[sc.Index] = bestVAH;
VAL[sc.Index] = bestVAL;
}

Date Time Of Last Edit: 2025-07-24 13:17:33