Login Page - Create Account

Support Board


Date/Time: Tue, 26 Aug 2025 10:23:12 +0000



Post From: ACSIL help

[2025-07-17 05:48:49]
User781731 - Posts: 70
I'm trying to calculate "Finish Ask Volume Bid Volume Difference (Finish AskVol BidVol Diff)" in my custom study.

My script correctly identifies the "Ask Volume Bid Volume Difference High" and "Ask Volume Bid Volume Difference Low"; which are the two elements needed for "Finish Ask Volume Bid Volume Difference (Finish AskVol BidVol Diff)" - see below.

These are the two formulas, one of which must be used to calculate the Finish value:

If the Ask Volume Bid Volume Difference High was more recently increased as compared to the Ask Volume Bid Volume Difference Low being more recently decreased, then Finish AskVol BidVol Diff equals the Ask Volume Bid Volume Difference for the bar minus the Ask Volume Bid Volume Difference High for the bar.

Otherwise, if the Ask Volume Bid Volume Difference Low was more recently decreased as compared to the Ask Volume Bid Volume Difference High being more recently increased, then Finish AskVol BidVol Diff equals the Ask Volume Bid Volume Difference for the bar minus the Ask Volume Bid Volume Difference Low for the bar.

Knowing which formula to use depends on which of the following two conditions is true:
- Ask Volume Bid Volume Difference High was more recently increased as compared to the Ask Volume Bid Volume Difference Low being more recently decreased
- Ask Volume Bid Volume Difference Low was more recently decreased as compared to the Ask Volume Bid Volume Difference High being more recently increased

This is what I'm unsure about. Can anyone help?

Here is the code:

#include "sierrachart.h"

SCDLLName("A-Finish")

// A-Finish: Tick-by-tick Finish Delta via Time & Sales only
SCSFExport scsf_AFinish(SCStudyInterfaceRef sc)
{
SCSubgraphRef Finish = sc.Subgraph[0];
SCSubgraphRef MaxDelta = sc.Subgraph[1];
SCSubgraphRef MinDelta = sc.Subgraph[2];
SCInputRef Lookback = sc.Input[0];

if (sc.SetDefaults)
{
sc.GraphName = "A-Finish";
sc.StudyDescription = "Finish Delta using only Time & Sales data.";
sc.AutoLoop = 0;
sc.UpdateAlways = 1;
sc.MaintainAdditionalChartDataArrays = 1;
sc.GraphRegion = 0;

Finish.Name = "Finish";
Finish.DrawStyle = DRAWSTYLE_LINE;
Finish.PrimaryColor = RGB(255,128,0);

MaxDelta.Name = "Max Delta";
MaxDelta.DrawStyle = DRAWSTYLE_IGNORE;
MinDelta.Name = "Min Delta";
MinDelta.DrawStyle = DRAWSTYLE_IGNORE;

Lookback.Name = "Bars to Log";
Lookback.SetInt(10);
Lookback.SetIntLimits(1,100);
return;
}

if (sc.IsFullRecalculation)
{
// Process all historical bars except the last (still forming)
for (int barToProcess = 0; barToProcess < sc.ArraySize - 1; ++barToProcess)
{
float runningDelta = 0.0f;
float maxDelta = 0.0f;
float minDelta = 0.0f;
int lastMaxIndex = -1;
int lastMinIndex = -1;
float totalAskVol = 0.0f;
float totalBidVol = 0.0f;

s_IntradayRecord record;
int subIndex = 0;
int readSuccess = 1;
bool firstIteration = true;
while (readSuccess)
{
IntradayFileLockActionEnum lockAction = IFLA_NO_CHANGE;
if (firstIteration) {
lockAction = IFLA_LOCK_READ_HOLD;
firstIteration = false;
}
readSuccess = sc.ReadIntradayFileRecordForBarIndexAndSubIndex(barToProcess, subIndex, record, lockAction);
if (readSuccess)
{
runningDelta += record.AskVolume;
runningDelta -= record.BidVolume;
totalAskVol += record.AskVolume;
totalBidVol += record.BidVolume;
if (subIndex == 0 || runningDelta > maxDelta)
{
maxDelta = runningDelta;
lastMaxIndex = subIndex;
}
if (subIndex == 0 || runningDelta < minDelta)
{
minDelta = runningDelta;
lastMinIndex = subIndex;
}
++subIndex;
}
}
sc.ReadIntradayFileRecordForBarIndexAndSubIndex(-1, -1, record, IFLA_RELEASE_AFTER_READ);
MaxDelta[barToProcess] = maxDelta;
MinDelta[barToProcess] = minDelta;
float finalDelta = totalAskVol - totalBidVol;
float finishValue = 0.0f;
if (finalDelta > 0)
finishValue = finalDelta - maxDelta;
else if (finalDelta < 0)
finishValue = finalDelta - minDelta;
else
finishValue = 0.0f;
Finish[barToProcess] = finishValue;
}
}
else
{
// Real-time: only process the most recent closed bar
static int lastProcessedBar = -1;
int currentIndex = sc.Index;
if (sc.GetBarHasClosedStatus(currentIndex - 1) != BHCS_BAR_HAS_CLOSED)
return;
int barToProcess = currentIndex - 1;
if (barToProcess == lastProcessedBar)
return;
lastProcessedBar = barToProcess;
float runningDelta = 0.0f;
float maxDelta = 0.0f;
float minDelta = 0.0f;
int lastMaxIndex = -1;
int lastMinIndex = -1;
float totalAskVol = 0.0f;
float totalBidVol = 0.0f;
s_IntradayRecord record;
int subIndex = 0;
int readSuccess = 1;
bool firstIteration = true;
while (readSuccess)
{
IntradayFileLockActionEnum lockAction = IFLA_NO_CHANGE;
if (firstIteration) {
lockAction = IFLA_LOCK_READ_HOLD;
firstIteration = false;
}
readSuccess = sc.ReadIntradayFileRecordForBarIndexAndSubIndex(barToProcess, subIndex, record, lockAction);
if (readSuccess)
{
runningDelta += record.AskVolume;
runningDelta -= record.BidVolume;
totalAskVol += record.AskVolume;
totalBidVol += record.BidVolume;
if (subIndex == 0 || runningDelta > maxDelta)
{
maxDelta = runningDelta;
lastMaxIndex = subIndex;
}
if (subIndex == 0 || runningDelta < minDelta)
{
minDelta = runningDelta;
lastMinIndex = subIndex;
}
++subIndex;
}
}
sc.ReadIntradayFileRecordForBarIndexAndSubIndex(-1, -1, record, IFLA_RELEASE_AFTER_READ);
MaxDelta[barToProcess] = maxDelta;
MinDelta[barToProcess] = minDelta;
float finalDelta = totalAskVol - totalBidVol;
float finishValue = 0.0f;
if (finalDelta > 0)
finishValue = finalDelta - maxDelta;
else if (finalDelta < 0)
finishValue = finalDelta - minDelta;
else
finishValue = 0.0f;
Finish[barToProcess] = finishValue;
}

// Log for last N bars (show correct values for all processed bars)
int N = Lookback.GetInt();
int currentIndex = sc.Index;
int startBar = max(0, currentIndex - N);
for (int b = startBar; b < currentIndex; ++b)
{
// Calculate Delta for the bar (total AskVol - BidVol)
float delta = Finish[b]; // Default to Finish for backward compatibility
if (b < sc.ArraySize) {
// Recalculate delta for the bar if possible
float totalAskVol = 0.0f;
float totalBidVol = 0.0f;
s_IntradayRecord record;
int subIndex = 0;
int readSuccess = 1;
bool firstIteration = true;
while (readSuccess)
{
IntradayFileLockActionEnum lockAction = IFLA_NO_CHANGE;
if (firstIteration) {
lockAction = IFLA_LOCK_READ_HOLD;
firstIteration = false;
}
readSuccess = sc.ReadIntradayFileRecordForBarIndexAndSubIndex(b, subIndex, record, lockAction);
if (readSuccess)
{
totalAskVol += record.AskVolume;
totalBidVol += record.BidVolume;
++subIndex;
}
}
sc.ReadIntradayFileRecordForBarIndexAndSubIndex(-1, -1, record, IFLA_RELEASE_AFTER_READ);
delta = totalAskVol - totalBidVol;
}
// Calculate Finish %
float finish = Finish[b];
float finishPercent = 0.0f;
if (finish < 0 && MaxDelta[b] != 0)
finishPercent = (fabsf(finish) / fabsf(MaxDelta[b])) * 100.0f;
else if (finish > 0 && MinDelta[b] != 0)
finishPercent = (fabsf(finish) / fabsf(MinDelta[b])) * 100.0f;
// If finish is 0 or divisor is 0, percent remains 0
SCString msg;
msg.Format("%s, Delta: %.0f, Max: %.0f, Min: %.0f, Finish: %.0f, Finish %%: %.0f",
sc.FormatDateTime(sc.BaseDateTimeIn[b]).GetChars(),
delta,
MaxDelta[b],
MinDelta[b],
finish,
finishPercent);
sc.AddMessageToLog(msg, 0);
}
}

Date Time Of Last Edit: 2025-07-17 12:04:08