Support Board
Date/Time: Thu, 26 Dec 2024 18:36:03 +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
|