Login Page - Create Account

Support Board


Date/Time: Fri, 17 May 2024 19:14:38 +0000



Post From: Orderflowanalytics-style reversal bars.

[2014-01-23 17:20:42]
norvik_ - Posts: 106
I had modified code of P&F Bars from ASC_Source folder. It seems works correct.
#include "C:\SierraChart\ACS_Source\sierrachart.h"

SCDLLName("OFAChart")


SCSFExport scsf_OFAChart(SCStudyInterfaceRef sc)
{
SCSubgraphRef Open = sc.Subgraph[SC_OPEN];
SCSubgraphRef High = sc.Subgraph[SC_HIGH];
SCSubgraphRef Low = sc.Subgraph[SC_LOW];
SCSubgraphRef Last = sc.Subgraph[SC_LAST];
SCSubgraphRef Volume = sc.Subgraph[SC_VOLUME];
SCSubgraphRef NumTrades = sc.Subgraph[SC_NT];
SCSubgraphRef OHLCAvg = sc.Subgraph[SC_OHLC];
SCSubgraphRef HLCAvg = sc.Subgraph[SC_HLC];
SCSubgraphRef HLAvg = sc.Subgraph[SC_HL];
SCSubgraphRef BidVol = sc.Subgraph[SC_BIDVOL];
SCSubgraphRef AskVol = sc.Subgraph[SC_ASKVOL];
SCSubgraphRef UpTickVol = sc.Subgraph[SC_UPVOL];
SCSubgraphRef DownTickVol = sc.Subgraph[SC_DOWNVOL];
SCSubgraphRef BidTrades = sc.Subgraph[SC_BIDNT];
SCSubgraphRef AskTrades = sc.Subgraph[SC_ASKNT];
SCSubgraphRef BidAskDiffMax = sc.Subgraph[SC_ASKBID_DIFF_HIGH];
SCSubgraphRef BidAskDiffMin = sc.Subgraph[SC_ASKBID_DIFF_LOW];
SCSubgraphRef NumberOfBoxes = sc.Subgraph[PF_NUM_BOXES_ARRAY];
SCSubgraphRef DirectionArray = sc.Subgraph[PF_DIRECTION_ARRAY];
SCSubgraphRef TrueLast = sc.Subgraph[PF_TRUELAST_ARRAY];

const int ArrayCount = PF_TRUELAST_ARRAY + 1;

    SCInputRef InitialRangeTicks = sc.Input[0];
SCInputRef ReversalSize = sc.Input[1];
SCInputRef AllowOneBoxReversals = sc.Input[2];
SCInputRef NewBarAtStartOfDay = sc.Input[3];
SCInputRef IgnoreLastBarUntilComplete = sc.Input[4];

if (sc.SetDefaults)
{
sc.GraphName = "OFA Chart";

sc.GraphRegion = 0;
sc.StandardChartHeader = 1;
sc.IsCustomChart = 1;
sc.GraphDrawType = GDT_CANDLESTICK;
sc.DrawZeros = 0;
sc.FreeDLL = 1;

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

High.Name = "High";
High.DrawStyle = DRAWSTYLE_LINE;

High.PrimaryColor = RGB(0,255,0);

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

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

Volume.Name = "Volume";
Volume.DrawStyle = DRAWSTYLE_IGNORE;
Volume.PrimaryColor = RGB(255,255,255);

NumTrades.Name = "# of Trades / OI";
NumTrades.DrawStyle = DRAWSTYLE_IGNORE;
NumTrades.PrimaryColor = RGB(255,255,255);

OHLCAvg.Name = "OHLC Avg";
OHLCAvg.DrawStyle = DRAWSTYLE_IGNORE;
OHLCAvg.PrimaryColor = RGB(255,255,255);

HLCAvg.Name = "HLC Avg";
HLCAvg.DrawStyle = DRAWSTYLE_IGNORE;
HLCAvg.PrimaryColor = RGB(255,255,255);

HLAvg.Name = "HL Avg";
HLAvg.DrawStyle = DRAWSTYLE_IGNORE;
HLAvg.PrimaryColor = RGB(255,255,255);

BidVol.Name = "Bid Vol";
BidVol.DrawStyle = DRAWSTYLE_IGNORE;
BidVol.PrimaryColor = RGB(255,255,255);

AskVol.Name = "Ask Vol";
AskVol.DrawStyle = DRAWSTYLE_IGNORE;
AskVol.PrimaryColor = RGB(255,255,255);

NumberOfBoxes.Name = "Number of Boxes";
NumberOfBoxes.DrawStyle = DRAWSTYLE_IGNORE;
NumberOfBoxes.PrimaryColor = RGB(0xFF,0x99,0x00);

TrueLast.Name = "True Last";
TrueLast.DrawStyle = DRAWSTYLE_IGNORE;
TrueLast.PrimaryColor = RGB(255,255,255);

InitialRangeTicks.Name = "Target range (ticks):";
          InitialRangeTicks.SetInt(6);

ReversalSize.Name = "Reversal Size";
ReversalSize.SetFloat(3.0f);
ReversalSize.SetFloatLimits(FLT_MIN, FLT_MAX);

AllowOneBoxReversals.Name = "Allow One Box Reversals";

AllowOneBoxReversals.SetYesNo(1);

NewBarAtStartOfDay.Name = "New Bar at Start of Day";
NewBarAtStartOfDay.SetYesNo(0);

IgnoreLastBarUntilComplete.Name = "Ignore Last Bar Until Completed";
IgnoreLastBarUntilComplete.SetYesNo(0);

return;
}


struct s_PFStorage
{
int PriorOutArraySize;
float PriorOutData[ArrayCount];
float High;
float Low;
int Index;
float targetRange;
};

s_PFStorage* p_PFStorage = (s_PFStorage*)sc.StorageBlock;

SCDateTime& NextSessionStart = sc.PersistVars->scdt1;

int InputIndex = sc.UpdateStartIndex;
int AvgStartIndex = 0;

if (InputIndex == 0)
{
sc.ResizeArrays(0);

AvgStartIndex = 0;

// Clear the last state data
memset(p_PFStorage, 0, sizeof(p_PFStorage));

p_PFStorage->Index = -1;
p_PFStorage->targetRange = sc.RoundToTickSize(InitialRangeTicks.GetInt() * sc.TickSize, sc.TickSize);

if (!sc.AddElements(1))
return;

sc.DateTimeOut[0] = sc.BaseDateTimeIn[0];

Open[0] = sc.Open[0];
High[0] = sc.Close[0];

Low[0] = sc.Close[0];

Last[0] = sc.Close[0];
TrueLast[0] = sc.Close[0];

NextSessionStart = sc.GetTradingDayStartDateTimeOfBar(sc.BaseDateTimeIn[0]) + 1*DAYS;


NumTrades.Name = "# of Trades";

sc.GraphName.Format("OFAChart %.6gx%g %s",ReversalSize.GetFloat(),sc.GetStudyNameFromChart(sc.ChartNumber, 0).GetChars());
}

else if (!IgnoreLastBarUntilComplete.GetYesNo())
{
AvgStartIndex = p_PFStorage->PriorOutArraySize - 1;

// Restore array to size just before processing last input bar (sc.BaseDataIn) and restore state of last output bar.

sc.ResizeArrays(p_PFStorage->PriorOutArraySize);

for (int SubgraphIndex = 0; SubgraphIndex < ArrayCount; ++SubgraphIndex)
{
sc.Subgraph[SubgraphIndex][AvgStartIndex] = p_PFStorage->PriorOutData[SubgraphIndex];
}

}

int OutputIndex = sc.DateTimeOut.GetArraySize() - 1;
if (InputIndex == 0)
InputIndex = 1;

for (; InputIndex < sc.ArraySize; ++InputIndex)
{
bool NewBar = false;

if (IgnoreLastBarUntilComplete.GetYesNo() && sc.GetBarHasClosedStatus(InputIndex)== BHCS_BAR_HAS_NOT_CLOSED)
return;

if (NewBarAtStartOfDay.GetYesNo() != 0)
{
SCDateTime IndexDateTime = sc.BaseDateTimeIn[InputIndex];

if (IndexDateTime >= NextSessionStart)
{
sc.CalculateOHLCAverages(OutputIndex);

if (!sc.AddElements(1))
return;

NewBar = true;
OutputIndex = sc.DateTimeOut.GetArraySize() - 1;

sc.DateTimeOut[OutputIndex] = sc.BaseDateTimeIn[InputIndex];

Open[OutputIndex] = sc.Open[InputIndex];
High[OutputIndex] = sc.Close[InputIndex];
Low[OutputIndex] = sc.Close[InputIndex];
Last[OutputIndex] = sc.Close[InputIndex];
TrueLast[OutputIndex] = sc.Close[InputIndex];

NextSessionStart = sc.GetTradingDayStartDateTimeOfBar(IndexDateTime) + 1*DAYS;
}
}

// Remember state of last P&F bar when reach last input bar because last
// input bar can change due to updating, causing for example a new P&F bar
// to be added when on a later update no new bar is added.
if (!IgnoreLastBarUntilComplete.GetYesNo() && InputIndex == sc.ArraySize - 1)
{
p_PFStorage->PriorOutArraySize = OutputIndex + 1;
for (int SubgraphIndex = 0; SubgraphIndex < ArrayCount; ++SubgraphIndex)
{
p_PFStorage->PriorOutData[SubgraphIndex] = sc.Subgraph[SubgraphIndex][OutputIndex];
}
}
          
// Determine our initial direction if not known
if (DirectionArray[OutputIndex] == 0.0f)
{
if (Last[OutputIndex] > sc.Close[InputIndex])
DirectionArray[OutputIndex] = -1; // Down

else if (Last[OutputIndex] < sc.Close[InputIndex])
DirectionArray[OutputIndex] = 1; // Up
}

if (DirectionArray[OutputIndex] == 0.0f)
continue; // No direction


bool UseHighFirst;

int OpenToHighLow = sc.CompareOpenToHighLow(sc.Open[InputIndex],sc.High[InputIndex], sc.Low[InputIndex], sc.BaseGraphValueFormat);

if(OpenToHighLow == 1)
UseHighFirst = true;
else if(OpenToHighLow == -1)
UseHighFirst = false;
else if (sc.FormattedEvaluate(sc.Open[InputIndex] , sc.BaseGraphValueFormat,GREATER_OPERATOR, sc.Close[InputIndex], sc.BaseGraphValueFormat))
UseHighFirst = true;
else if (sc.FormattedEvaluate(sc.Open[InputIndex] , sc.BaseGraphValueFormat,LESS_OPERATOR, sc.Close[InputIndex], sc.BaseGraphValueFormat))
UseHighFirst = false;
else if (DirectionArray[OutputIndex] == 1) // Up Bar
UseHighFirst = true;
else
UseHighFirst = false;

for (int PassNumber=0; PassNumber<2; PassNumber++)
{
if (DirectionArray[OutputIndex] == 1)
{
if ((UseHighFirst && PassNumber == 0 ) || (!UseHighFirst &&PassNumber ==1))
{
if (sc.FormattedEvaluate(sc.High[InputIndex],sc.BaseGraphValueFormat, GREATER_EQUAL_OPERATOR, High[OutputIndex],sc.BaseGraphValueFormat))
{
High[OutputIndex] = sc.High[InputIndex];
}
}

if ((PassNumber == 0) || (UseHighFirst && PassNumber == 1))
{
  
                      float trueRange = High[OutputIndex] - Low[OutputIndex];

if ((sc.FormattedEvaluate(sc.Low[InputIndex],sc.BaseGraphValueFormat, LESS_EQUAL_OPERATOR, High[OutputIndex] - sc.TickSize *ReversalSize.GetFloat(), sc.BaseGraphValueFormat))&&(sc.FormattedEvaluate(trueRange, sc.ValueFormat, GREATER_OPERATOR, p_PFStorage->targetRange, sc.ValueFormat)))
{
Last[OutputIndex] = High[OutputIndex];

bool SetOpen = false;

if (AllowOneBoxReversals.GetYesNo())
{
// Calculate the number of boxes for the column
NumberOfBoxes[OutputIndex] =(float)sc.Round(High[OutputIndex] - Low[OutputIndex]);

sc.CalculateOHLCAverages(OutputIndex);

if (!sc.AddElements(1))
return;

NewBar = true;
OutputIndex++;
sc.DateTimeOut[OutputIndex] = sc.BaseDateTimeIn[InputIndex];

High[OutputIndex] = High[OutputIndex - 1];

SetOpen = true;
}

DirectionArray[OutputIndex] = -1;
Low[OutputIndex] = sc.Low[InputIndex];

if (SetOpen)
Open[OutputIndex] = Low[OutputIndex];

}
}

if (UseHighFirst)
PassNumber++;

}
else// down column
{
if ((!UseHighFirst && PassNumber == 0) || (UseHighFirst && PassNumber ==1))
{
if (sc.FormattedEvaluate(sc.Low[InputIndex] ,sc.BaseGraphValueFormat, LESS_EQUAL_OPERATOR, Low[OutputIndex] ,sc.BaseGraphValueFormat))
{

Low[OutputIndex] = sc.Low[InputIndex];
}
}

if (PassNumber == 0 || (!UseHighFirst && PassNumber == 1))
{
  
                      float trueRange = High[OutputIndex] - Low[OutputIndex];
  
if ((sc.FormattedEvaluate(sc.High[InputIndex] ,sc.BaseGraphValueFormat, GREATER_EQUAL_OPERATOR, Low[OutputIndex] + sc.TickSize *ReversalSize.GetFloat(), sc.BaseGraphValueFormat))&&(sc.FormattedEvaluate(trueRange, sc.ValueFormat, GREATER_OPERATOR, p_PFStorage->targetRange, sc.ValueFormat)))
{
Last[OutputIndex] = High[OutputIndex];

Last[OutputIndex] = Low[OutputIndex];

bool SetOpen = false;
if (AllowOneBoxReversals.GetYesNo())
{
// Calculate the number of boxes for the column
NumberOfBoxes[OutputIndex] = High[OutputIndex] - Low[OutputIndex];

sc.CalculateOHLCAverages(OutputIndex);

if (!sc.AddElements(1))
return;

NewBar = true;
OutputIndex++;
sc.DateTimeOut[OutputIndex] =sc.BaseDateTimeIn[InputIndex];

Low[OutputIndex] = Low[OutputIndex - 1];

SetOpen = true;
}

DirectionArray[OutputIndex] = 1;
High[OutputIndex] = sc.High[InputIndex];

if (SetOpen)
Open[OutputIndex] = High[OutputIndex];
}
}

if (!UseHighFirst)
PassNumber++;

}//else down column
} // PassNumber for loop

TrueLast[OutputIndex] = sc.Close[InputIndex];
Last[OutputIndex] = sc.Close[InputIndex];
sc.CalculateOHLCAverages(OutputIndex);

NumberOfBoxes[OutputIndex] = (float)sc.Round((High[OutputIndex] -Low[OutputIndex])/sc.TickSize);

// Add in volume and open interest
Volume[OutputIndex] += sc.Volume[InputIndex];
NumTrades[OutputIndex] += sc.OpenInterest[InputIndex];
float BidAskDiffHigh = 0;
float BidAskDiffLow = 0;
if (sc.BaseDataIn.GetArraySize() >= SC_ASKBID_DIFF_LOW+1)
{
BidAskDiffHigh = AskVol[OutputIndex] - BidVol[OutputIndex] +sc.BaseDataIn[SC_ASKBID_DIFF_HIGH][InputIndex];
BidAskDiffLow = AskVol[OutputIndex] - BidVol[OutputIndex] +sc.BaseDataIn[SC_ASKBID_DIFF_LOW][InputIndex];
}
BidVol[OutputIndex] += sc.BidVolume[InputIndex];
AskVol[OutputIndex] += sc.AskVolume[InputIndex];
UpTickVol[OutputIndex] += sc.UpTickVolume[InputIndex];
DownTickVol[OutputIndex] += sc.DownTickVolume[InputIndex];
BidTrades[OutputIndex] += sc.NumberOfBidTrades[InputIndex];
AskTrades[OutputIndex] += sc.NumberOfAskTrades[InputIndex];

if (NewBar || BidAskDiffHigh > BidAskDiffMax[OutputIndex])
BidAskDiffMax[OutputIndex] = BidAskDiffHigh;

if (NewBar || BidAskDiffLow < BidAskDiffMin[OutputIndex])
BidAskDiffMin[OutputIndex] = BidAskDiffLow;
}
}

Date Time Of Last Edit: 2014-01-23 17:23:07