#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers // Windows header file #include #include "sierrachart.h" #include "scstudyfunctions.h" /*============================================================================*/ SCSFExport scsf_SumAllChartsBar(SCStudyInterfaceRef sc) { SCSubgraphRef Open = sc.Subgraph[0]; SCSubgraphRef High = sc.Subgraph[1]; SCSubgraphRef Low = sc.Subgraph[2]; SCSubgraphRef Last = sc.Subgraph[3]; SCSubgraphRef Volume = sc.Subgraph[4]; SCSubgraphRef OpenInterest = sc.Subgraph[5]; SCSubgraphRef OHLCAvg = sc.Subgraph[6]; SCSubgraphRef HLCAvg = sc.Subgraph[7]; SCSubgraphRef HLAvg = sc.Subgraph[8]; SCSubgraphRef BidVol = sc.Subgraph[9]; SCSubgraphRef AskVol = sc.Subgraph[10]; if (sc.SetDefaults) { // Set the configuration and defaults sc.GraphName = "Sum All Charts (Bar)" ; sc.StudyDescription = "Sum All Charts (Bar)."; sc.GraphDrawType = GDT_OHLCBAR; sc.StandardChartHeader = 1; sc.ValueFormat = 2; Open.Name = "Open"; Open.DrawStyle = DRAWSTYLE_LINE; Open.PrimaryColor = RGB(0,255,0); Open.DrawZeros = false; High.Name = "High"; High.DrawStyle = DRAWSTYLE_LINE; High.PrimaryColor = RGB(0,255,0); High.DrawZeros = false; Low.Name = "Low"; Low.DrawStyle = DRAWSTYLE_LINE; Low.PrimaryColor = RGB(0,255,0); Low.DrawZeros = false; Last.Name = "Last"; Last.DrawStyle = DRAWSTYLE_LINE; Last.PrimaryColor = RGB(0,255,0); Last.DrawZeros = false; Volume.Name = "Volume"; Volume.DrawStyle = DRAWSTYLE_IGNORE; Volume.PrimaryColor = RGB(255,0,0); Volume.DrawZeros = false; OpenInterest.Name = "# of Trades / OI"; OpenInterest.DrawStyle = DRAWSTYLE_IGNORE; OpenInterest.PrimaryColor = RGB(0,0,255); OpenInterest.DrawZeros = false; OHLCAvg.Name = "OHLC Avg"; OHLCAvg.DrawStyle = DRAWSTYLE_IGNORE; OHLCAvg.PrimaryColor = RGB(127,0,255); OHLCAvg.DrawZeros = false; HLCAvg.Name = "HLC Avg"; HLCAvg.DrawStyle = DRAWSTYLE_IGNORE; HLCAvg.PrimaryColor = RGB(0,255,255); HLCAvg.DrawZeros = false; HLAvg.Name = "HL Avg"; HLAvg.DrawStyle = DRAWSTYLE_IGNORE; HLAvg.PrimaryColor = RGB(0,127,255); HLAvg.DrawZeros = false; BidVol.Name = "Bid Vol"; BidVol.DrawStyle = DRAWSTYLE_IGNORE; BidVol.PrimaryColor = RGB(0,255,0); BidVol.DrawZeros = false; AskVol.Name = "Ask Vol"; AskVol.DrawStyle = DRAWSTYLE_IGNORE; AskVol.PrimaryColor = RGB(0,255,0); AskVol.DrawZeros = false; return; } // Initialize the data in the destination subgraphs to 0 before looping through the charts. for (int DataIndex = sc.UpdateStartIndex; DataIndex < sc.ArraySize; DataIndex++) { // Loop through the subgraphs for (int SubgraphIndex = 0; SubgraphIndex < 6; SubgraphIndex++) { sc.Subgraph[SubgraphIndex][DataIndex] = 0; } } // Loop through the charts for (int ChartIndex = 1; ChartIndex < 201; ChartIndex++) { SCGraphData ReferenceArrays; sc.GetChartBaseData(-ChartIndex, ReferenceArrays); if (ReferenceArrays[SC_OPEN].GetArraySize() < 1) continue; // Loop through the data indexes for (int DataIndex = sc.UpdateStartIndex; DataIndex < sc.ArraySize; DataIndex++) { // Get the matching index int RefDataIndex = sc.GetNearestMatchForDateTimeIndex(ChartIndex, DataIndex); // Loop through the subgraphs for (int SubgraphIndex = 0; SubgraphIndex < 6; SubgraphIndex++) { // Add in the value of the current chart sc.Subgraph[SubgraphIndex][DataIndex] += ReferenceArrays[SubgraphIndex][RefDataIndex]; } sc.CalculateOHLCAverages(DataIndex); } } return; } /*============================================================================*/ SCSFExport scsf_MultiplyAllChartsBar(SCStudyInterfaceRef sc) { SCSubgraphRef Open = sc.Subgraph[0]; SCSubgraphRef High = sc.Subgraph[1]; SCSubgraphRef Low = sc.Subgraph[2]; SCSubgraphRef Last = sc.Subgraph[3]; SCSubgraphRef Volume = sc.Subgraph[4]; SCSubgraphRef OpenInterest = sc.Subgraph[5]; SCSubgraphRef OHLCAvg = sc.Subgraph[6]; SCSubgraphRef HLCAvg = sc.Subgraph[7]; SCSubgraphRef HLAvg = sc.Subgraph[8]; SCSubgraphRef BidVol = sc.Subgraph[9]; SCSubgraphRef AskVol = sc.Subgraph[10]; if (sc.SetDefaults) { // Set the configuration and defaults sc.GraphName = "Multiply All Charts" ; sc.GraphDrawType = GDT_OHLCBAR; sc.StandardChartHeader = 1; sc.ValueFormat = 2; Open.Name = "Open"; Open.DrawStyle = DRAWSTYLE_LINE; Open.PrimaryColor = RGB(0,255,0); Open.DrawZeros = false; High.Name = "High"; High.DrawStyle = DRAWSTYLE_LINE; High.PrimaryColor = RGB(0,255,0); High.DrawZeros = false; Low.Name = "Low"; Low.DrawStyle = DRAWSTYLE_LINE; Low.PrimaryColor = RGB(0,255,0); Low.DrawZeros = false; Last.Name = "Last"; Last.DrawStyle = DRAWSTYLE_LINE; Last.PrimaryColor = RGB(0,255,0); Last.DrawZeros = false; Volume.Name = "Volume"; Volume.DrawStyle = DRAWSTYLE_IGNORE; Volume.PrimaryColor = RGB(0,0,255); Volume.DrawZeros = false; OpenInterest.Name = "# of Trades / OI"; OpenInterest.DrawStyle = DRAWSTYLE_IGNORE; OpenInterest.PrimaryColor = RGB(127,0,255); OpenInterest.DrawZeros = false; OHLCAvg.Name = "OHLC Avg"; OHLCAvg.DrawStyle = DRAWSTYLE_IGNORE; OHLCAvg.PrimaryColor = RGB(0,255,0); OHLCAvg.DrawZeros = false; HLCAvg.Name = "HLC Avg"; HLCAvg.DrawStyle = DRAWSTYLE_IGNORE; HLCAvg.PrimaryColor = RGB(0,255,255); HLCAvg.DrawZeros = false; HLAvg.Name = "HL Avg"; HLAvg.DrawStyle = DRAWSTYLE_IGNORE; HLAvg.PrimaryColor = RGB(0,127,255); HLAvg.DrawZeros = false; BidVol.Name = "Bid Vol"; BidVol.DrawStyle = DRAWSTYLE_IGNORE; BidVol.PrimaryColor = RGB(0,255,0); BidVol.DrawZeros = false; AskVol.Name = "Ask Vol"; AskVol.DrawStyle = DRAWSTYLE_IGNORE; AskVol.PrimaryColor = RGB(0,255,0); AskVol.DrawZeros = false; return; } // Initialize the data in the destination subgraphs to 1.0 before looping through the charts. for (int DataIndex = sc.UpdateStartIndex; DataIndex < sc.ArraySize; DataIndex++) { // Loop through the subgraphs for (int SubgraphIndex = 0; SubgraphIndex < 6; SubgraphIndex++) { sc.Subgraph[SubgraphIndex][DataIndex] = 1.0; } } // Loop through the charts. Up to 200. for (int ChartIndex = 1; ChartIndex < 201; ChartIndex++) { SCGraphData ReferenceArrays; sc.GetChartBaseData(-ChartIndex, ReferenceArrays); if (ReferenceArrays[SC_OPEN].GetArraySize() < 1) continue; // Loop through the data indexes for (int DataIndex = sc.UpdateStartIndex; DataIndex < sc.ArraySize; DataIndex++) { // Get the matching index int RefDataIndex = sc.GetNearestMatchForDateTimeIndex(ChartIndex, DataIndex); // Loop through the subgraphs for (int SubgraphIndex = 0; SubgraphIndex < 6; SubgraphIndex++) { // Add in the value of the current chart sc.Subgraph[SubgraphIndex][DataIndex] *= ReferenceArrays[SubgraphIndex][RefDataIndex]; } sc.CalculateOHLCAverages(DataIndex); } } return; } /*============================================================================*/ SCSFExport scsf_SumChartsFromList(SCStudyInterfaceRef sc) { SCSubgraphRef Open = sc.Subgraph[0]; SCSubgraphRef High = sc.Subgraph[1]; SCSubgraphRef Low = sc.Subgraph[2]; SCSubgraphRef Last = sc.Subgraph[3]; SCSubgraphRef Volume = sc.Subgraph[4]; SCSubgraphRef OpenInterest = sc.Subgraph[5]; SCSubgraphRef OHLCAvg = sc.Subgraph[6]; SCSubgraphRef HLCAvg = sc.Subgraph[7]; SCSubgraphRef HLAvg = sc.Subgraph[8]; SCSubgraphRef BidVol = sc.Subgraph[9]; SCSubgraphRef AskVol = sc.Subgraph[10]; SCInputRef Divisor = sc.Input[0]; SCInputRef SyncCharts = sc.Input[1]; if (sc.SetDefaults) { // Set the configuration and defaults sc.GraphName = "Sum Charts From List" ; sc.StudyDescription = "Sum Charts From List."; sc.GraphDrawType = GDT_OHLCBAR; sc.StandardChartHeader = 1; sc.ValueFormat = 2; Open.Name = "Open"; Open.DrawStyle = DRAWSTYLE_LINE; Open.PrimaryColor = RGB(0,255,0); Open.DrawZeros = false; High.Name = "High"; High.DrawStyle = DRAWSTYLE_LINE; High.PrimaryColor = RGB(0,255,0); High.DrawZeros = false; Low.Name = "Low"; Low.DrawStyle = DRAWSTYLE_LINE; Low.PrimaryColor = RGB(0,255,0); Low.DrawZeros = false; Last.Name = "Last"; Last.DrawStyle = DRAWSTYLE_LINE; Last.PrimaryColor = RGB(0,255,0); Last.DrawZeros = false; Volume.Name = "Volume"; Volume.DrawStyle = DRAWSTYLE_IGNORE; Volume.PrimaryColor = RGB(255,0,0); Volume.DrawZeros = false; OpenInterest.Name = "# of Trades / OI"; OpenInterest.DrawStyle = DRAWSTYLE_IGNORE; OpenInterest.PrimaryColor = RGB(0,0,255); OpenInterest.DrawZeros = false; OHLCAvg.Name = "OHLC Avg"; OHLCAvg.DrawStyle = DRAWSTYLE_IGNORE; OHLCAvg.PrimaryColor = RGB(127,0,255); OHLCAvg.DrawZeros = false; HLCAvg.Name = "HLC Avg"; HLCAvg.DrawStyle = DRAWSTYLE_IGNORE; HLCAvg.PrimaryColor = RGB(0,255,255); HLCAvg.DrawZeros = false; HLAvg.Name = "HL Avg"; HLAvg.DrawStyle = DRAWSTYLE_IGNORE; HLAvg.PrimaryColor = RGB(0,127,255); HLAvg.DrawZeros = false; BidVol.Name = "Bid Vol"; BidVol.DrawStyle = DRAWSTYLE_IGNORE; BidVol.PrimaryColor = RGB(0,255,0); BidVol.DrawZeros = false; AskVol.Name = "Ask Vol"; AskVol.DrawStyle = DRAWSTYLE_IGNORE; AskVol.PrimaryColor = RGB(0,255,0); AskVol.DrawZeros = false; Divisor.Name = "Divisor. Use 0 for divisor equal to number of charts."; Divisor.SetFloat(1); SyncCharts.Name = "Synchronize charts"; SyncCharts.SetYesNo(false); sc.TextInputName = "List of Chart Numbers (comma separated)"; return; } // Do data processing int Sync = 1; if(SyncCharts.GetYesNo()) Sync = -1; // Make a copy of the list of chart numbers from the text input SCString ChartNumberList = sc.TextInput; // Get each of the chart numbers (from the text input) and put them into a // vector. std::vector ChartNumbers; std::vector ChartMultipliers; char* TokenContext = NULL; char* Token = strtok_s((char *)ChartNumberList.GetChars(), ",", &TokenContext); while (Token != NULL) { ChartNumbers.push_back(atoi(Token)); float Multiplier = 0.0; char* FoundMultiplier = strchr(Token, '*'); if (FoundMultiplier != NULL) Multiplier =(float) atof(FoundMultiplier + 1); if (Multiplier == 0.0) Multiplier = 1.0; ChartMultipliers.push_back(Multiplier); // Get the next chart number Token = strtok_s(NULL, ",", &TokenContext); } float DivisorValue = Divisor.GetFloat(); if (DivisorValue == 0) DivisorValue = (float)ChartNumbers.size(); int Index = 0; for (std::vector::iterator Iter_ChartNumber = ChartNumbers.begin(); Iter_ChartNumber != ChartNumbers.end(); ++Iter_ChartNumber, ++Index) { int ChartNumber = *Iter_ChartNumber; float ChartMultiplier = ChartMultipliers[Index]; SCGraphData ReferenceArrays; sc.GetChartBaseData(ChartNumber*Sync, ReferenceArrays); if (ReferenceArrays[SC_OPEN].GetArraySize() < 1) continue; // Loop through the data indexes for (int DataIndex = sc.UpdateStartIndex; DataIndex < sc.ArraySize; DataIndex++) { // Get the matching index int RefDataIndex = sc.GetNearestMatchForDateTimeIndex(ChartNumber, DataIndex); // Loop through the subgraphs for (int SubgraphIndex = 0; SubgraphIndex <= SC_LAST; SubgraphIndex++) { // Add in the value of the current chart if (Index == 0) { sc.Subgraph[SubgraphIndex][DataIndex] = ReferenceArrays[SubgraphIndex][RefDataIndex] * ChartMultiplier / DivisorValue; } else { sc.Subgraph[SubgraphIndex][DataIndex] += ReferenceArrays[SubgraphIndex][RefDataIndex] * ChartMultiplier / DivisorValue; } } sc.Subgraph[ SC_HIGH][DataIndex] = max(sc.Subgraph[SC_OPEN][DataIndex], max(sc.Subgraph[SC_HIGH][DataIndex], max(sc.Subgraph[SC_LOW][DataIndex],sc.Subgraph[SC_LAST][DataIndex]) ) ); sc.Subgraph[SC_LOW][DataIndex] = min(sc.Subgraph[SC_OPEN][DataIndex], min(sc.Subgraph[SC_HIGH][DataIndex], min(sc.Subgraph[SC_LOW][DataIndex],sc.Subgraph[SC_LAST][DataIndex]) ) ); // Loop through the subgraphs for (int SubgraphIndex = SC_VOLUME; SubgraphIndex <= SC_NUM_TRADES; SubgraphIndex++) { // Add in the value of the current chart if (Index == 0) sc.Subgraph[SubgraphIndex][DataIndex] = ReferenceArrays[SubgraphIndex][RefDataIndex] * (1.0f / ChartMultiplier) / DivisorValue; else sc.Subgraph[SubgraphIndex][DataIndex] += ReferenceArrays[SubgraphIndex][RefDataIndex] * (1.0f / ChartMultiplier) / DivisorValue; } sc.CalculateOHLCAverages(DataIndex); } } } /*============================================================================ ----------------------------------------------------------------------------*/ SCSFExport scsf_BidAskVolumeRatio(SCStudyInterfaceRef sc) { SCSubgraphRef VolRatioAvg = sc.Subgraph[0]; SCSubgraphRef ZeroLine = sc.Subgraph[1]; SCFloatArrayRef ExtraArrayRatio = sc.Subgraph[0].Arrays[0]; SCInputRef InMALength = sc.Input[0]; SCInputRef InMAType = sc.Input[1]; SCInputRef InDifferenceCalculation = sc.Input[2]; if (sc.SetDefaults) { // Set the configuration and defaults sc.GraphName = "Bid Ask Volume Ratio"; sc.StudyDescription = "Bid Ask Volume Ratio"; sc.AutoLoop = 1; VolRatioAvg.Name = "Vol Ratio Avg"; VolRatioAvg.DrawStyle = DRAWSTYLE_LINE; VolRatioAvg.PrimaryColor = RGB(0,255,0); VolRatioAvg.DrawZeros = false; ZeroLine.Name = "Zero Line"; ZeroLine.DrawStyle = DRAWSTYLE_LINE; ZeroLine.PrimaryColor = RGB(255,0,255); ZeroLine.DrawZeros = true; InMALength.Name = "Length"; InMALength.SetInt(14); InMALength.SetIntLimits(1,MAX_STUDY_LENGTH); InMAType.Name= "Moving Average Type"; InMAType.SetMovAvgType(MOVAVGTYPE_EXPONENTIAL); InDifferenceCalculation.Name = "Difference Calculation Method"; InDifferenceCalculation.SetCustomInputStrings("Ask Volume - Bid Volume;Bid Volume - Ask Volume"); InDifferenceCalculation.SetCustomInputIndex(0); return; } //if(sc.GetBarHasClosedStatus() == BHCS_BAR_HAS_NOT_CLOSED) //return; // Do data processing float UpVol = sc.AskVolume[sc.Index]; float DownVol = sc.BidVolume[sc.Index]; float TotalVol = UpVol + DownVol; if(InDifferenceCalculation.GetIndex() == 0 && TotalVol > 0) ExtraArrayRatio[sc.Index] = 100.0f * (UpVol - DownVol) / TotalVol; else if(InDifferenceCalculation.GetIndex() == 1 && TotalVol > 0) ExtraArrayRatio[sc.Index] = 100.0f * (DownVol - UpVol) / TotalVol; else ExtraArrayRatio[sc.Index] = 0.0f; sc.MovingAverage(ExtraArrayRatio, VolRatioAvg, InMAType.GetMovAvgType(), InMALength.GetInt()); } /*============================================================================ ----------------------------------------------------------------------------*/ SCSFExport scsf_StudyAngle(SCStudyInterfaceRef sc) { SCSubgraphRef Angle = sc.Subgraph[0]; SCSubgraphRef ZeroLine = sc.Subgraph[1]; SCInputRef InInputData = sc.Input[0]; SCInputRef InLength = sc.Input[1]; SCInputRef InValuePerPoint = sc.Input[2]; SCInputRef InSkipCalculationAtStartOfTradingDay = sc.Input[3]; if (sc.SetDefaults) { // Set the configuration and defaults sc.GraphName = "Study Angle"; sc.AutoLoop = 1; Angle.Name = "Angle"; Angle.DrawStyle = DRAWSTYLE_LINE; Angle.PrimaryColor = RGB(0,255,0); Angle.DrawZeros= false; ZeroLine.Name = "Zero Line"; ZeroLine.DrawStyle = DRAWSTYLE_LINE; ZeroLine.PrimaryColor = RGB(255,0,255); ZeroLine.DrawZeros= true; InInputData.Name = "Input Data"; InInputData.SetInputDataIndex(0); InLength.Name = "Length"; InLength.SetInt(10); InLength.SetIntLimits(1,MAX_STUDY_LENGTH); InValuePerPoint.Name = "Value Per Point"; InValuePerPoint.SetFloat(1.0f); InSkipCalculationAtStartOfTradingDay.Name = "Skip Calculation at Start of Trading Day"; InSkipCalculationAtStartOfTradingDay.SetYesNo(false); return; } int Length = InLength.GetInt(); sc.DataStartIndex = Length; if (InValuePerPoint.GetFloat() == 0.0f) InValuePerPoint.SetFloat(0.01f); int &r_IndexOfNewDay = sc.GetPersistentInt(1); if (sc.IsFullRecalculation && sc.Index == 0) r_IndexOfNewDay = -1; // Do data processing bool SkipCalculation = false; if (InSkipCalculationAtStartOfTradingDay.GetYesNo()) { if (sc.IsNewTradingDay(sc.Index)) { r_IndexOfNewDay = sc.Index; } SkipCalculation = r_IndexOfNewDay == sc.Index || (sc.Index - Length) < r_IndexOfNewDay ; } if(!SkipCalculation) { SCFloatArrayRef InData = sc.BaseData[InInputData.GetInputDataIndex()]; float BackValue = InData[sc.Index - Length]; float CurrentValue = InData[sc.Index]; float PointChange = (CurrentValue - BackValue) / InValuePerPoint.GetFloat(); Angle[sc.Index] = (float)(atan2((double)PointChange, (double)Length) * 180.0 / M_PI); } else { Angle[sc.Index] = 0; } } /*==========================================================================*/ SCSFExport scsf_DetrendedOscillator(SCStudyInterfaceRef sc) { // Section 1 - Set the configuration variables SCSubgraphRef DPO = sc.Subgraph[0]; SCSubgraphRef overbought = sc.Subgraph[1]; SCSubgraphRef oversold = sc.Subgraph[2]; SCFloatArrayRef MA = sc.Subgraph[0].Arrays[0]; SCInputRef I_Length = sc.Input[0]; SCInputRef I_overbought = sc.Input[1]; SCInputRef I_oversold = sc.Input[2]; SCInputRef I_MovingAverageType = sc.Input[3]; if (sc.SetDefaults) { // Set the configuration and defaults sc.GraphName = "Detrended Oscillator"; sc.StudyDescription = "Detrended Oscillator."; sc.AutoLoop = 1; // true DPO.Name = "DO"; DPO.DrawStyle = DRAWSTYLE_LINE; DPO.PrimaryColor = RGB(0,255,0); overbought.Name = "Level 1"; overbought.DrawStyle = DRAWSTYLE_LINE; overbought.PrimaryColor = RGB(255,255,0); oversold.Name = "Level 2"; oversold.DrawStyle = DRAWSTYLE_LINE; oversold.PrimaryColor = RGB(255,255,0); I_Length.Name = "Length"; I_Length.SetInt(20); I_overbought.Name = "Overbought Level"; I_overbought.SetFloat(0.5); I_oversold.Name = "Oversold Level"; I_oversold.SetFloat(-0.5); I_MovingAverageType.Name = "Moving Average Type"; I_MovingAverageType.SetMovAvgType(MOVAVGTYPE_SIMPLE); return; } // Section 2 - Do data processing here sc.DataStartIndex = I_Length.GetInt(); int N = I_Length.GetInt()/2; overbought[sc.Index] = I_overbought.GetFloat(); oversold[sc.Index] = I_oversold.GetFloat(); sc.MovingAverage(sc.Close, MA, I_MovingAverageType.GetMovAvgType() , sc.Index, N); int N2 = (N/2) + 1; DPO[sc.Index] = (sc.Close[sc.Index] - MA[sc.Index - N2]); } /*==========================================================================*/ SCSFExport scsf_RangeBarPredictor(SCStudyInterfaceRef sc) { // Section 1 - Set the configuration variables SCSubgraphRef High = sc.Subgraph[0]; SCSubgraphRef Low = sc.Subgraph[1]; if (sc.SetDefaults) { // Set the configuration and defaults sc.GraphName = "Range Bar Predictor"; sc.StudyDescription = "Range Bar Predictor."; sc.GraphRegion = 0; sc.AutoLoop = 1; // true High.Name = "Predicted High"; High.DrawStyle = DRAWSTYLE_DASH; High.PrimaryColor = RGB(0, 255, 0); High.LineWidth = 2; High.DrawZeros = false; Low.Name = "Predicted Low"; Low.DrawStyle = DRAWSTYLE_DASH; Low.PrimaryColor = RGB(255, 0, 0); Low.LineWidth = 2; Low.DrawZeros = false; return; } // Section 2 - Do data processing here n_ACSIL::s_BarPeriod BarPeriodParameters; sc.GetBarPeriodParameters(BarPeriodParameters); if (!(BarPeriodParameters.IntradayChartBarPeriodType == IBPT_RANGE_IN_TICKS_FILL_GAPS || BarPeriodParameters.IntradayChartBarPeriodType == IBPT_RANGE_IN_TICKS_NEW_BAR_ON_RANGE_MET_OPEN_EQUALS_PRIOR_CLOSE || BarPeriodParameters.IntradayChartBarPeriodType == IBPT_RANGE_IN_TICKS_NEWBAR_ON_RANGEMET || BarPeriodParameters.IntradayChartBarPeriodType == IBPT_RANGE_IN_TICKS_OPEN_EQUAL_CLOSE || BarPeriodParameters.IntradayChartBarPeriodType == IBPT_RANGE_IN_TICKS_STANDARD || BarPeriodParameters.IntradayChartBarPeriodType == IBPT_RANGE_IN_TICKS_TRUE)) { return; } float RangePerBar = BarPeriodParameters.IntradayChartBarPeriodParameter1 * sc.TickSize; if (sc.Index == sc.ArraySize - 1) { High[sc.Index] = sc.Low[sc.Index] + RangePerBar; Low[sc.Index] = sc.High[sc.Index] - RangePerBar; } else { High[sc.Index] = 0; Low[sc.Index] = 0; } } /*==========================================================================*/ SCSFExport scsf_RenkoBarPredictor(SCStudyInterfaceRef sc) { SCSubgraphRef High = sc.Subgraph[0]; SCSubgraphRef Low = sc.Subgraph[1]; if (sc.SetDefaults) { // Set the configuration and defaults sc.GraphName = "Renko Bar Predictor"; sc.StudyDescription = "Renko Bar Predictor."; sc.GraphRegion = 0; sc.AutoLoop = 1; // true High.Name = "Predicted High"; High.DrawStyle = DRAWSTYLE_DASH; High.PrimaryColor = RGB(0,255,0); High.LineWidth = 2; High.DrawZeros = false; Low.Name = "Predicted Low"; Low.DrawStyle = DRAWSTYLE_DASH; Low.PrimaryColor = RGB(255,0,0); Low.LineWidth = 2; Low.DrawZeros = false; return; } int Index = sc.Index; if (Index > 0 && Index == sc.ArraySize - 1) { float PriorRenkoOpen = sc.BaseData[SC_RENKO_OPEN][Index-1]; float PriorRenkoClose = sc.BaseData[SC_RENKO_CLOSE][Index-1]; bool PriorBarUp = PriorRenkoOpen < PriorRenkoClose; n_ACSIL::s_BarPeriod BarPeriod; sc.GetBarPeriodParameters(BarPeriod); int RenkoTicksPerBar = BarPeriod.IntradayChartBarPeriodParameter1; int RenkoTrendOpenOffsetInTicks = BarPeriod.IntradayChartBarPeriodParameter2; int RenkoReversalOpenOffsetInTicks = BarPeriod.IntradayChartBarPeriodParameter3; if (BarPeriod.IntradayChartBarPeriodParameter4 <= 2)//exceeded mode RenkoTrendOpenOffsetInTicks -= 1; if (PriorBarUp) { if (BarPeriod.IntradayChartBarPeriodType != IBPT_FLEX_RENKO_IN_TICKS_INVERSE_SETTINGS) { High[Index] = PriorRenkoClose - RenkoTrendOpenOffsetInTicks * sc.TickSize + RenkoTicksPerBar * sc.TickSize; Low[Index] = PriorRenkoClose + RenkoReversalOpenOffsetInTicks * sc.TickSize - 2.0f * RenkoTicksPerBar * sc.TickSize; } else { High[Index] = PriorRenkoClose + RenkoTrendOpenOffsetInTicks * sc.TickSize; Low[Index] = PriorRenkoClose - RenkoReversalOpenOffsetInTicks * sc.TickSize; } } else { if (BarPeriod.IntradayChartBarPeriodType != IBPT_FLEX_RENKO_IN_TICKS_INVERSE_SETTINGS) { High[Index] = PriorRenkoClose - RenkoReversalOpenOffsetInTicks * sc.TickSize + 2.0f * RenkoTicksPerBar * sc.TickSize; Low[Index] = PriorRenkoClose + RenkoTrendOpenOffsetInTicks * sc.TickSize - RenkoTicksPerBar * sc.TickSize; } else { High[Index] = PriorRenkoClose + RenkoReversalOpenOffsetInTicks * sc.TickSize; Low[Index] = PriorRenkoClose - RenkoTrendOpenOffsetInTicks * sc.TickSize; } } } else { High[Index] = 0; Low[Index] = 0; } } /*============================================================================*/ SCSFExport scsf_FastStochastic(SCStudyInterfaceRef sc) { SCSubgraphRef PercentK = sc.Subgraph[0]; SCSubgraphRef PercentD = sc.Subgraph[1]; SCSubgraphRef Line1 = sc.Subgraph[2]; SCSubgraphRef Line2 = sc.Subgraph[3]; SCInputRef Unused2 = sc.Input[2]; SCInputRef KLength = sc.Input[3]; SCInputRef DLength = sc.Input[4]; SCInputRef Line1Value = sc.Input[5]; SCInputRef Line2Value = sc.Input[6]; SCInputRef MovAvgType = sc.Input[7]; SCInputRef InputDataHigh = sc.Input[8]; SCInputRef InputDataLow = sc.Input[9]; SCInputRef InputDataLast = sc.Input[10]; if (sc.SetDefaults) { sc.GraphName = "Stochastic - Fast"; sc.ValueFormat = 2; PercentK.Name = "%K"; PercentK.DrawStyle = DRAWSTYLE_LINE; PercentK.PrimaryColor = RGB(0,255,0); PercentK.DrawZeros = true; PercentD.Name = "%D"; PercentD.DrawStyle = DRAWSTYLE_LINE; PercentD.PrimaryColor = RGB(255,0,255); PercentD.DrawZeros = true; Line1.Name = "Line1"; Line1.DrawStyle = DRAWSTYLE_LINE; Line1.PrimaryColor = RGB(255,255,0); Line1.DrawZeros = true; Line2.Name = "Line2"; Line2.DrawStyle = DRAWSTYLE_LINE; Line2.PrimaryColor = RGB(255,127,0); Line2.DrawZeros = true; Unused2.Name = ""; Unused2.SetInt(10); Unused2.SetIntLimits(1,MAX_STUDY_LENGTH); KLength.Name = "%K Length"; KLength.SetInt(10); KLength.SetIntLimits(1,MAX_STUDY_LENGTH); DLength.Name = "%D Length"; DLength.SetInt(3); DLength.SetIntLimits(1,MAX_STUDY_LENGTH); Line1Value.Name = "Line1 Value"; Line1Value.SetFloat(70); Line2Value.Name = "Line2 Value"; Line2Value.SetFloat(30); MovAvgType.Name = "Moving Average Type"; MovAvgType.SetMovAvgType(MOVAVGTYPE_SIMPLE); InputDataHigh.Name = "Input Data for High"; InputDataHigh.SetInputDataIndex(SC_HIGH); InputDataLow.Name = "Input Data for Low"; InputDataLow.SetInputDataIndex(SC_LOW); InputDataLast.Name = "Input Data for Last"; InputDataLast.SetInputDataIndex(SC_LAST); sc.AutoLoop = true; return; } sc.DataStartIndex = KLength.GetInt() + DLength.GetInt(); sc.Stochastic( sc.BaseData[InputDataHigh.GetInputDataIndex()], sc.BaseData[InputDataLow.GetInputDataIndex()], sc.BaseData[InputDataLast.GetInputDataIndex()], PercentK, // Data member is Fast %K KLength.GetInt(), DLength.GetInt(), 0, MovAvgType.GetMovAvgType() ); PercentD[sc.Index] = PercentK.Arrays[0][sc.Index]; // Fast %D (Slow %K) Line1[sc.Index] = Line1Value.GetFloat(); Line2[sc.Index] = Line2Value.GetFloat(); } /*============================================================================*/ SCSFExport scsf_KDFastStochastic(SCStudyInterfaceRef sc) { SCSubgraphRef PercentK = sc.Subgraph[0]; SCSubgraphRef PercentD = sc.Subgraph[1]; SCSubgraphRef Line1 = sc.Subgraph[2]; SCSubgraphRef Line2 = sc.Subgraph[3]; SCInputRef Unused2 = sc.Input[2]; SCInputRef KLength = sc.Input[3]; SCInputRef DLength = sc.Input[4]; SCInputRef Line1Value = sc.Input[5]; SCInputRef Line2Value = sc.Input[6]; SCInputRef MovAvgType = sc.Input[7]; SCInputRef InputDataHigh = sc.Input[8]; SCInputRef InputDataLow = sc.Input[9]; SCInputRef InputDataLast = sc.Input[10]; if (sc.SetDefaults) { sc.GraphName = "KD - Fast"; sc.ValueFormat = 2; PercentK.Name = "%K"; PercentK.DrawStyle = DRAWSTYLE_LINE; PercentK.PrimaryColor = RGB(0,255,0); PercentK.DrawZeros = true; PercentD.Name = "%D"; PercentD.DrawStyle = DRAWSTYLE_LINE; PercentD.PrimaryColor = RGB(255,0,255); PercentD.DrawZeros = true; Line1.Name = "Line1"; Line1.DrawStyle = DRAWSTYLE_LINE; Line1.PrimaryColor = RGB(255,255,0); Line1.DrawZeros = true; Line2.Name = "Line2"; Line2.DrawStyle = DRAWSTYLE_LINE; Line2.PrimaryColor = RGB(255,127,0); Line2.DrawZeros = true; Unused2.Name = ""; Unused2.SetInt(10); Unused2.SetIntLimits(1,MAX_STUDY_LENGTH); KLength.Name = "%K Length"; KLength.SetInt(10); KLength.SetIntLimits(1,MAX_STUDY_LENGTH); DLength.Name = "%D Length"; DLength.SetInt(3); DLength.SetIntLimits(1,MAX_STUDY_LENGTH); Line1Value.Name = "Line1 Value"; Line1Value.SetFloat(70); Line2Value.Name = "Line2 Value"; Line2Value.SetFloat(30); MovAvgType.Name = "Moving Average Type"; MovAvgType.SetMovAvgType(MOVAVGTYPE_SIMPLE); InputDataHigh.Name = "Input Data for High"; InputDataHigh.SetInputDataIndex(SC_HIGH); InputDataLow.Name = "Input Data for Low"; InputDataLow.SetInputDataIndex(SC_LOW); InputDataLast.Name = "Input Data for Last"; InputDataLast.SetInputDataIndex(SC_LAST); sc.AutoLoop = true; return; } sc.DataStartIndex = KLength.GetInt() + DLength.GetInt(); sc.Stochastic( sc.BaseData[InputDataHigh.GetInputDataIndex()], sc.BaseData[InputDataLow.GetInputDataIndex()], sc.BaseData[InputDataLast.GetInputDataIndex()], PercentK, // Data member is Fast %K KLength.GetInt(), DLength.GetInt(), 0, MovAvgType.GetMovAvgType() ); PercentD[sc.Index] = PercentK.Arrays[0][sc.Index]; // Fast %D (Slow %K) Line1[sc.Index] = Line1Value.GetFloat(); Line2[sc.Index] = Line2Value.GetFloat(); } /*============================================================================*/ SCSFExport scsf_SlowStochastic(SCStudyInterfaceRef sc) { SCSubgraphRef SlowK = sc.Subgraph[0]; SCSubgraphRef SlowD = sc.Subgraph[1]; SCSubgraphRef Line1 = sc.Subgraph[2]; SCSubgraphRef Line2 = sc.Subgraph[3]; SCSubgraphRef Temp4 = sc.Subgraph[4]; SCInputRef FastKLength = sc.Input[2]; SCInputRef FastDLength = sc.Input[3]; SCInputRef SlowDLength = sc.Input[4]; SCInputRef Line1Value = sc.Input[5]; SCInputRef Line2Value = sc.Input[6]; SCInputRef MovAvgType = sc.Input[7]; SCInputRef InputDataHigh = sc.Input[8]; SCInputRef InputDataLow = sc.Input[9]; SCInputRef InputDataLast = sc.Input[10]; SCInputRef UpdateFlag = sc.Input[11]; if (sc.SetDefaults) { sc.GraphName = "Stochastic - Slow"; sc.ValueFormat = 2; SlowK.Name = "Slow %K"; SlowK.DrawStyle = DRAWSTYLE_LINE; SlowK.PrimaryColor = RGB(0,255,0); SlowK.DrawZeros = true; SlowD.Name = "Slow %D"; SlowD.DrawStyle = DRAWSTYLE_LINE; SlowD.PrimaryColor = RGB(255,0,255); SlowD.DrawZeros = true; Line1.Name = "Line1"; Line1.DrawStyle = DRAWSTYLE_LINE; Line1.PrimaryColor = RGB(255,255,0); Line1.DrawZeros = true; Line2.Name = "Line2"; Line2.DrawStyle = DRAWSTYLE_LINE; Line2.PrimaryColor = RGB(255,127,0); Line2.DrawZeros = true; FastKLength.Name = "Fast %K Length"; FastKLength.SetInt(10); FastKLength.SetIntLimits(1,MAX_STUDY_LENGTH); FastDLength.Name = "Fast %D Length (Slow %K)"; FastDLength.SetInt(3); FastDLength.SetIntLimits(1,MAX_STUDY_LENGTH); SlowDLength.Name = "Slow %D Length"; SlowDLength.SetInt(3); SlowDLength.SetIntLimits(1,MAX_STUDY_LENGTH); Line1Value.Name = "Line1 Value"; Line1Value.SetFloat(70); Line2Value.Name = "Line2 Value"; Line2Value.SetFloat(30); MovAvgType.Name = "Moving Average Type"; MovAvgType.SetMovAvgType(MOVAVGTYPE_SIMPLE); InputDataHigh.Name = "Input Data for High"; InputDataHigh.SetInputDataIndex(SC_HIGH); InputDataLow.Name = "Input Data for Low"; InputDataLow.SetInputDataIndex(SC_LOW); InputDataLast.Name = "Input Data for Last"; InputDataLast.SetInputDataIndex(SC_LAST); UpdateFlag.SetInt(1); //update flag sc.AutoLoop = true; return; } sc.DataStartIndex = FastKLength.GetInt() + FastDLength.GetInt() + SlowDLength.GetInt(); sc.Stochastic( sc.BaseData[InputDataHigh.GetInputDataIndex()], sc.BaseData[InputDataLow.GetInputDataIndex()], sc.BaseData[InputDataLast.GetInputDataIndex()], Temp4, // Data member is Fast %K FastKLength.GetInt(), FastDLength.GetInt(), SlowDLength.GetInt(), MovAvgType.GetMovAvgType() ); SlowK[sc.Index] = Temp4.Arrays[0][sc.Index]; SlowD[sc.Index] = Temp4.Arrays[1][sc.Index]; Line1[sc.Index] = Line1Value.GetFloat(); Line2[sc.Index] = Line2Value.GetFloat(); return; } /*============================================================================*/ SCSFExport scsf_KDSlowStochastic(SCStudyInterfaceRef sc) { SCSubgraphRef SlowK = sc.Subgraph[0]; SCSubgraphRef SlowD = sc.Subgraph[1]; SCSubgraphRef Line1 = sc.Subgraph[2]; SCSubgraphRef Line2 = sc.Subgraph[3]; SCSubgraphRef Temp4 = sc.Subgraph[4]; SCInputRef FastKLength = sc.Input[2]; SCInputRef FastDLength = sc.Input[3]; SCInputRef SlowDLength = sc.Input[4]; SCInputRef Line1Value = sc.Input[5]; SCInputRef Line2Value = sc.Input[6]; SCInputRef MovAvgType = sc.Input[7]; SCInputRef InputDataHigh = sc.Input[8]; SCInputRef InputDataLow = sc.Input[9]; SCInputRef InputDataLast = sc.Input[10]; if (sc.SetDefaults) { sc.GraphName = "KD - Slow"; sc.ValueFormat = 2; SlowK.Name = "Slow %K"; SlowK.DrawStyle = DRAWSTYLE_LINE; SlowK.PrimaryColor = RGB(0,255,0); SlowK.DrawZeros = true; SlowD.Name = "Slow %D"; SlowD.DrawStyle = DRAWSTYLE_LINE; SlowD.PrimaryColor = RGB(255,0,255); SlowD.DrawZeros = true; Line1.Name = "Line1"; Line1.DrawStyle = DRAWSTYLE_LINE; Line1.PrimaryColor = RGB(255,255,0); Line1.DrawZeros = true; Line2.Name = "Line2"; Line2.DrawStyle = DRAWSTYLE_LINE; Line2.PrimaryColor = RGB(255,127,0); Line2.DrawZeros = true; FastKLength.Name = "Fast %K Length"; FastKLength.SetInt(10); FastKLength.SetIntLimits(1,MAX_STUDY_LENGTH); FastDLength.Name = "Fast %D Length (Slow %K)"; FastDLength.SetInt(3); FastDLength.SetIntLimits(1,MAX_STUDY_LENGTH); SlowDLength.Name = "Slow %D Length"; SlowDLength.SetInt(3); SlowDLength.SetIntLimits(1,MAX_STUDY_LENGTH); Line1Value.Name = "Line1 Value"; Line1Value.SetFloat(70); Line2Value.Name = "Line2 Value"; Line2Value.SetFloat(30); MovAvgType.Name = "Moving Average Type"; MovAvgType.SetMovAvgType(MOVAVGTYPE_SIMPLE); InputDataHigh.Name = "Input Data for High"; InputDataHigh.SetInputDataIndex(SC_HIGH); InputDataLow.Name = "Input Data for Low"; InputDataLow.SetInputDataIndex(SC_LOW); InputDataLast.Name = "Input Data for Last"; InputDataLast.SetInputDataIndex(SC_LAST); sc.AutoLoop = true; return; } sc.DataStartIndex = FastKLength.GetInt() + FastDLength.GetInt() + SlowDLength.GetInt(); sc.Stochastic( sc.BaseData[InputDataHigh.GetInputDataIndex()], sc.BaseData[InputDataLow.GetInputDataIndex()], sc.BaseData[InputDataLast.GetInputDataIndex()], Temp4, // Data member is Fast %K FastKLength.GetInt(), FastDLength.GetInt(), SlowDLength.GetInt(), MovAvgType.GetMovAvgType() ); SlowK[sc.Index] = Temp4.Arrays[0][sc.Index]; SlowD[sc.Index] = Temp4.Arrays[1][sc.Index]; Line1[sc.Index] = Line1Value.GetFloat(); Line2[sc.Index] = Line2Value.GetFloat(); return; } /*============================================================================*/ SCSFExport scsf_DoubleTrix(SCStudyInterfaceRef sc) { // Section 1 - Set the configuration variables SCInputRef I_TRIXLength = sc.Input[0]; SCInputRef I_SigLineXMALen = sc.Input[1]; SCFloatArrayRef EMA1 = sc.Subgraph[0].Arrays[0]; SCFloatArrayRef EMA2 = sc.Subgraph[0].Arrays[1]; SCFloatArrayRef EMA3 = sc.Subgraph[0].Arrays[2]; SCSubgraphRef TRIXLine = sc.Subgraph[0]; SCSubgraphRef SignalLine = sc.Subgraph[1]; if (sc.SetDefaults) { sc.GraphName = "Double Trix"; sc.StudyDescription = "DoubleTrix."; sc.AutoLoop = 1; // true TRIXLine.Name = "TRIXLine"; TRIXLine.DrawStyle = DRAWSTYLE_LINE; TRIXLine.PrimaryColor = RGB(0,255,0); TRIXLine.LineWidth = 1; SignalLine.Name = "SignalLine"; SignalLine.DrawStyle = DRAWSTYLE_LINE; SignalLine.PrimaryColor = RGB(255,0,0); SignalLine.LineWidth = 1; I_TRIXLength.Name = "TRIXLength"; I_TRIXLength.SetInt(5); I_SigLineXMALen.Name = "SigLineXMALen"; I_SigLineXMALen.SetInt(3); return; } // Section 2 - Do data processing here int TRIXLength = I_TRIXLength.GetInt(); int SigLineXMALen = I_SigLineXMALen.GetInt(); sc.ExponentialMovAvg(sc.Close,EMA1,TRIXLength); sc.ExponentialMovAvg(EMA1,EMA2,TRIXLength); sc.ExponentialMovAvg(EMA2,EMA3,TRIXLength); if(EMA3[sc.Index-1] != 0) TRIXLine[sc.Index] = 10 * ( EMA3[sc.Index] - EMA3[sc.Index-1] ) / EMA3[sc.Index-1] ; else TRIXLine[sc.Index] = 0; sc.ExponentialMovAvg(TRIXLine,SignalLine,SigLineXMALen); } /*============================================================================*/ SCSFExport scsf_BollingerSqueeze2(SCStudyInterfaceRef sc) { SCSubgraphRef BollingerSqueezeSubgraph = sc.Subgraph[0]; SCSubgraphRef SqueezeZerosSubgraph = sc.Subgraph[1]; SCSubgraphRef KeltnerSubgraph = sc.Subgraph[2]; SCSubgraphRef BBSubgraph = sc.Subgraph[3]; SCSubgraphRef AverageTrueRange = sc.Subgraph[4]; SCSubgraphRef Momentum = sc.Subgraph[5]; SCSubgraphRef TopBollingerBand = sc.Subgraph[6]; SCSubgraphRef BottomBollingerBand = sc.Subgraph[7]; SCSubgraphRef TopKeltnerBand = sc.Subgraph[8]; SCSubgraphRef BottomKeltnerBand = sc.Subgraph[9]; SCInputRef InputInputData = sc.Input[0]; SCInputRef InputMAType = sc.Input[1]; SCInputRef InputKeltnerLength = sc.Input[2]; SCInputRef InputKeltnerTRAvgLength = sc.Input[3]; SCInputRef InputKeltnerMultiplier = sc.Input[4]; SCInputRef InputBollingerLength = sc.Input[5]; SCInputRef InputBollingerBandsMult = sc.Input[6]; SCInputRef InputMomentumLength = sc.Input[7]; if (sc.SetDefaults) { sc.GraphName="Bollinger Squeeze 2"; sc.StudyDescription="Bollinger Squeeze 2"; // Subgraphs BollingerSqueezeSubgraph.Name = "Momentum Avg"; BollingerSqueezeSubgraph.DrawStyle = DRAWSTYLE_BAR; BollingerSqueezeSubgraph.PrimaryColor = RGB(0,255,0); BollingerSqueezeSubgraph.SecondaryColor = RGB(255,0,0); BollingerSqueezeSubgraph.SecondaryColorUsed = true; SqueezeZerosSubgraph.Name = "Squeeze Indicator"; SqueezeZerosSubgraph.DrawStyle = DRAWSTYLE_POINT; SqueezeZerosSubgraph.LineWidth = 3; SqueezeZerosSubgraph.PrimaryColor = RGB(0,255,0); SqueezeZerosSubgraph.SecondaryColor = RGB(255,0,0); SqueezeZerosSubgraph.SecondaryColorUsed = true; Momentum.Name = "Momentum"; Momentum.DrawStyle = DRAWSTYLE_IGNORE; KeltnerSubgraph.Name = "Keltner Average"; KeltnerSubgraph.DrawStyle = DRAWSTYLE_IGNORE; AverageTrueRange.Name = "ATR"; AverageTrueRange.DrawStyle = DRAWSTYLE_IGNORE; TopBollingerBand.Name = "Top Bollinger Band"; TopBollingerBand.DrawStyle = DRAWSTYLE_IGNORE; BottomBollingerBand.Name = "Bottom Bollinger Band"; BottomBollingerBand.DrawStyle = DRAWSTYLE_IGNORE; TopKeltnerBand.Name = "Top Keltner Band"; TopKeltnerBand.DrawStyle = DRAWSTYLE_IGNORE; BottomKeltnerBand.Name = "Bottom Keltner Band"; BottomKeltnerBand.DrawStyle = DRAWSTYLE_IGNORE; // Data Inputs InputInputData.Name = "Input Data"; InputInputData.SetInputDataIndex(SC_LAST); InputMAType.Name="Moving Average Type for Internal Calculations"; InputMAType.SetMovAvgType(MOVAVGTYPE_SIMPLE); InputKeltnerLength.Name="Keltner Bands Length"; InputKeltnerLength.SetInt(20); InputKeltnerLength.SetIntLimits(1,MAX_STUDY_LENGTH); InputKeltnerTRAvgLength.Name = "Keltner True Range MovAvg Length"; InputKeltnerTRAvgLength.SetInt(20); InputKeltnerTRAvgLength.SetIntLimits(1,MAX_STUDY_LENGTH); InputKeltnerMultiplier.Name="Keltner Bands Multiplier"; InputKeltnerMultiplier.SetFloat(2.0f); InputKeltnerMultiplier.SetFloatLimits(.001f,(float)MAX_STUDY_LENGTH); InputBollingerLength.Name="Bollinger Bands Length"; InputBollingerLength.SetInt(20); InputBollingerLength.SetIntLimits(1,MAX_STUDY_LENGTH); InputBollingerBandsMult.Name="Bollinger Bands Multiplier"; InputBollingerBandsMult.SetFloat(10.0f); InputBollingerBandsMult.SetFloatLimits(.001f,(float)MAX_STUDY_LENGTH); InputMomentumLength.Name = "Momentum Length"; InputMomentumLength.SetInt(20); InputMomentumLength.SetIntLimits(1, MAX_STUDY_LENGTH); sc.AutoLoop = 1; sc.GraphRegion = 1; sc.ValueFormat = 3; return; } int InputData = InputInputData.GetInputDataIndex(); int MAType = InputMAType.GetMovAvgType(); int KeltnerLength = InputKeltnerLength.GetInt(); int KeltnerTRAVGLength = InputKeltnerTRAvgLength.GetInt(); float KeltnerMult = InputKeltnerMultiplier.GetFloat(); int BollingerLength = InputBollingerLength.GetInt(); float BandsMult = InputBollingerBandsMult.GetFloat(); int MomentumLength = InputMomentumLength.GetInt(); sc.DataStartIndex = max(KeltnerLength, max(KeltnerTRAVGLength, max(BollingerLength, MomentumLength))) - 1; // calculate Bollinger Bands sc.BollingerBands(sc.BaseData[InputData], BBSubgraph, BollingerLength, BandsMult, MAType); // BollingerSqueezeSubgraph.Arrays[0][sc.Index] = // sc.Close[sc.Index] - sc.Close[sc.Index - MomentumLength]; Momentum[sc.Index] = sc.Close[sc.Index] - sc.Close[sc.Index - MomentumLength]; sc.ExponentialMovAvg(Momentum, BollingerSqueezeSubgraph, MomentumLength); // calculate Keltner sc.Keltner( sc.BaseData,sc.BaseData[InputData], KeltnerSubgraph, KeltnerLength, MAType, KeltnerTRAVGLength, MOVAVGTYPE_WILDERS, KeltnerMult,KeltnerMult); // calculate Average True Range: SimpleMovingAverage(True Range), use Arrays[0] to store True Range AverageTrueRange.Arrays[0][sc.Index] = sc.GetTrueRange(sc.BaseData, sc.Index); sc.SimpleMovAvg(AverageTrueRange.Arrays[0], AverageTrueRange, KeltnerLength); TopKeltnerBand[sc.Index] = KeltnerSubgraph[sc.Index] + (KeltnerMult * AverageTrueRange[sc.Index]); BottomKeltnerBand[sc.Index] = KeltnerSubgraph[sc.Index] - (KeltnerMult * AverageTrueRange[sc.Index]); TopBollingerBand[sc.Index] = BBSubgraph.Arrays[0][sc.Index]; BottomBollingerBand[sc.Index] = BBSubgraph.Arrays[1][sc.Index]; if ((TopBollingerBand[sc.Index] > TopKeltnerBand[sc.Index]) && (BottomBollingerBand[sc.Index] < BottomKeltnerBand[sc.Index])) { SqueezeZerosSubgraph.DataColor[sc.Index] = SqueezeZerosSubgraph.PrimaryColor; SqueezeZerosSubgraph[sc.Index] = 0.0001f; } else { SqueezeZerosSubgraph.DataColor[sc.Index] = SqueezeZerosSubgraph.SecondaryColor; SqueezeZerosSubgraph[sc.Index] = -0.0001f; } if ((BollingerSqueezeSubgraph[sc.Index] > 0) && (BollingerSqueezeSubgraph[sc.Index] >= BollingerSqueezeSubgraph[sc.Index - 1])) { BollingerSqueezeSubgraph.DataColor[sc.Index] = BollingerSqueezeSubgraph.PrimaryColor; } else if ((BollingerSqueezeSubgraph[sc.Index] > 0) && (BollingerSqueezeSubgraph[sc.Index] < BollingerSqueezeSubgraph[sc.Index-1])) { BollingerSqueezeSubgraph.DataColor[sc.Index] = RGB(GetRValue(BollingerSqueezeSubgraph.PrimaryColor)/2, GetGValue(BollingerSqueezeSubgraph.PrimaryColor)/2, GetBValue(BollingerSqueezeSubgraph.PrimaryColor)/2); } else if ((BollingerSqueezeSubgraph[sc.Index] < 0) && (BollingerSqueezeSubgraph[sc.Index] <= BollingerSqueezeSubgraph[sc.Index-1])) BollingerSqueezeSubgraph.DataColor[sc.Index] = BollingerSqueezeSubgraph.SecondaryColor; else if ((BollingerSqueezeSubgraph[sc.Index] < 0) && (BollingerSqueezeSubgraph[sc.Index] > BollingerSqueezeSubgraph[sc.Index-1])) { BollingerSqueezeSubgraph.DataColor[sc.Index] = RGB(GetRValue(BollingerSqueezeSubgraph.SecondaryColor)/2, GetGValue(BollingerSqueezeSubgraph.SecondaryColor)/2, GetBValue(BollingerSqueezeSubgraph.SecondaryColor)/2); } } /*==========================================================================*/ SCSFExport scsf_BollingerSqueeze3(SCStudyInterfaceRef sc) { SCSubgraphRef Ratio = sc.Subgraph[0]; SCSubgraphRef SqueezeIndicator = sc.Subgraph[1]; SCInputRef Input_InputData = sc.Input[0]; SCInputRef Input_MovAvgType = sc.Input[1]; SCInputRef Input_Length = sc.Input[2]; SCInputRef Input_MovingAverageMultiplier = sc.Input[3]; SCInputRef Input_StandardDeviationMultiplier = sc.Input[4]; if (sc.SetDefaults) { sc.GraphName = "Bollinger Squeeze 3"; sc.AutoLoop = 1; sc.GraphRegion = 1; Ratio.Name = "Ratio"; Ratio.DrawStyle = DRAWSTYLE_BAR; Ratio.PrimaryColor = RGB(0, 255, 0); Ratio.SecondaryColor = RGB(255, 0, 0); //Ratio.SecondaryColorUsed = true; Ratio.DrawZeros = true; SqueezeIndicator.Name = "Squeeze Indicator"; SqueezeIndicator.DrawStyle = DRAWSTYLE_POINT; SqueezeIndicator.LineWidth = 3; SqueezeIndicator.PrimaryColor = RGB(0, 255, 0); SqueezeIndicator.SecondaryColor = RGB(255, 0, 0); SqueezeIndicator.SecondaryColorUsed = true; SqueezeIndicator.DrawZeros = true; Input_InputData.Name = "Input Data"; Input_InputData.SetInputDataIndex(SC_LAST); Input_MovAvgType.Name = "Moving Average Type for Calculations"; Input_MovAvgType.SetMovAvgType(MOVAVGTYPE_SIMPLE); Input_Length.Name = "Study Length"; Input_Length.SetInt(20); Input_Length.SetIntLimits(1, MAX_STUDY_LENGTH); Input_MovingAverageMultiplier.Name = "Moving Average Multiplier"; Input_MovingAverageMultiplier.SetFloat(1.5f); Input_StandardDeviationMultiplier.Name = "Standard Deviation Multiplier"; Input_StandardDeviationMultiplier.SetFloat(2.0f); return; } sc.StdDeviation(sc.BaseData[Input_InputData.GetInputDataIndex()], Ratio.Arrays[0], Input_Length.GetInt()); sc.TrueRange(sc.BaseData, Ratio.Arrays[1]); sc.MovingAverage(Ratio.Arrays[1], Ratio.Arrays[2], Input_MovAvgType.GetMovAvgType(), Input_Length.GetInt()); float StandardDeviationValue = Ratio.Arrays[0][sc.Index]; Ratio[sc.Index] = (Input_StandardDeviationMultiplier.GetFloat() * StandardDeviationValue) / (Input_MovingAverageMultiplier.GetFloat() * Ratio.Arrays[2][sc.Index]); if (Ratio[sc.Index] >= 1.0) SqueezeIndicator.DataColor[sc.Index] = SqueezeIndicator.PrimaryColor; //No squeeze else SqueezeIndicator.DataColor[sc.Index] = SqueezeIndicator.SecondaryColor; //Squeeze on } /*============================================================================*/ SCSFExport scsf_VolumeColoredBasedOnVolume(SCStudyInterfaceRef sc) { // Section 1 - Set the configuration variables SCSubgraphRef Volume = sc.Subgraph[0]; if (sc.SetDefaults) { // Set the configuration and defaults sc.GraphName = "Volume-Colored Based on Volume"; sc.AutoLoop = 1; // true Volume.Name = "Volume"; Volume.DrawStyle = DRAWSTYLE_BAR; Volume.SecondaryColorUsed = 1; Volume.PrimaryColor = RGB(0,255,0); Volume.SecondaryColor = RGB(255,0,0); return; } // Section 2 - Do data processing here Volume[sc.Index] = sc.Volume[sc.Index]; if(sc.Volume[sc.Index-1] <= sc.Volume[sc.Index]) Volume.DataColor[sc.Index] = Volume.PrimaryColor; else Volume.DataColor[sc.Index] = Volume.SecondaryColor; } /*==========================================================================*/ SCSFExport scsf_ExtendedArrayExample(SCStudyInterfaceRef sc) { SCSubgraphRef ADX = sc.Subgraph[0]; SCSubgraphRef ADXForwardShifted = sc.Subgraph[1]; SCSubgraphRef ADXForwardShiftedPlus = sc.Subgraph[2]; SCInputRef DXLength = sc.Input[3]; SCInputRef DXMovAngLength = sc.Input[4]; if (sc.SetDefaults) { sc.GraphName = "Extended Array Example"; sc.StudyDescription = "Extended Array Example. Based on ADX."; sc.AutoLoop = 1; sc.GraphRegion = 1; ADX.Name = "ADX"; ADX.DrawStyle = DRAWSTYLE_LINE; ADX.PrimaryColor = RGB(0,255,0); ADX.DrawZeros = false; ADXForwardShifted.Name = "ADX Forward Shifted"; ADXForwardShifted.DrawStyle = DRAWSTYLE_LINE; ADXForwardShifted.PrimaryColor = RGB(255,0,255); ADXForwardShifted.DrawZeros = false; // Set the ADXForwardShifted subgraph to support additional array elements for forward projection ADXForwardShifted.ExtendedArrayElementsToGraph = 50; ADXForwardShiftedPlus.Name = "ADX Plus Value"; ADXForwardShiftedPlus.DrawStyle = DRAWSTYLE_LINE; ADXForwardShiftedPlus.ExtendedArrayElementsToGraph = 50; ADXForwardShiftedPlus.PrimaryColor = RGB(255,255,0); ADXForwardShiftedPlus.DrawZeros = false; DXLength.Name = "DX Length"; DXLength.SetInt(14); DXLength.SetIntLimits(1, INT_MAX); DXMovAngLength.Name = "DX Mov Avg Length"; DXMovAngLength.SetInt(14); DXMovAngLength.SetIntLimits(1, INT_MAX); return; } // Do data processing sc.DataStartIndex = DXLength.GetInt() + DXMovAngLength.GetInt() - 1; // Calculate ADX sc.ADX( sc.BaseData, ADX, DXLength.GetInt(), DXMovAngLength.GetInt()); int NumberOfBarsToForwardShift = ADXForwardShifted.ExtendedArrayElementsToGraph; ADXForwardShifted[sc.Index] = ADX[sc.Index-NumberOfBarsToForwardShift]; ADXForwardShiftedPlus[sc.Index] = ADXForwardShifted[sc.Index] + 10; // Extended elements are cleared when the number of bars in the chart grows. Therefore, we need to fill them in every time. However, only when we are on the final index when using sc.AutoLoop = 1. if(sc.Index+1 >= sc.ArraySize) { for (int i = sc.ArraySize;i < sc.ArraySize + NumberOfBarsToForwardShift ;i++) { ADXForwardShifted[i] = ADX[i-NumberOfBarsToForwardShift]; ADXForwardShiftedPlus[i] = ADXForwardShifted[i] + 10; } } return; } /*==========================================================================*/ SCSFExport scsf_ForwardProjectionBars(SCStudyInterfaceRef sc) { SCSubgraphRef Open = sc.Subgraph[0]; SCSubgraphRef High = sc.Subgraph[1]; SCSubgraphRef Low = sc.Subgraph[2]; SCSubgraphRef Last = sc.Subgraph[3]; SCInputRef Input_NumberOfBarsToProjectForward = sc.Input[0]; if (sc.SetDefaults) { sc.GraphName = "Forward Projection Bars"; sc.AutoLoop = 0; sc.GraphRegion = 0; sc.GraphDrawType=GDT_OHLCBAR; sc.ValueFormat = VALUEFORMAT_INHERITED; Open.Name = "Open"; Open.DrawStyle = DRAWSTYLE_LINE; Open.PrimaryColor = RGB(0, 255, 0); Open.DrawZeros = false; High.Name = "High"; High.DrawStyle = DRAWSTYLE_LINE; High.PrimaryColor = RGB(0,255,0); High.DrawZeros = false; Low.Name = "Low"; Low.DrawStyle = DRAWSTYLE_LINE; Low.PrimaryColor = RGB(0,255,0); Low.DrawZeros = false; Last.Name = "Last"; Last.DrawStyle = DRAWSTYLE_LINE; Last.PrimaryColor = RGB(0,255,0); Last.DrawZeros = false; Input_NumberOfBarsToProjectForward.Name = "Number of Bars to Project Forward"; Input_NumberOfBarsToProjectForward.SetInt(10); return; } // Do data processing int NumberOfBarsToProjectForward = Input_NumberOfBarsToProjectForward.GetInt(); Open.ExtendedArrayElementsToGraph = NumberOfBarsToProjectForward; High.ExtendedArrayElementsToGraph = NumberOfBarsToProjectForward; Low.ExtendedArrayElementsToGraph = NumberOfBarsToProjectForward; Last.ExtendedArrayElementsToGraph = NumberOfBarsToProjectForward; for (int BarIndex = sc.ArraySize - NumberOfBarsToProjectForward; BarIndex < sc.ArraySize; BarIndex++) { Open[BarIndex + NumberOfBarsToProjectForward] = sc.Open[BarIndex]; High[BarIndex + NumberOfBarsToProjectForward] = sc.High[BarIndex]; Low[BarIndex + NumberOfBarsToProjectForward] = sc.Low[BarIndex]; Last[BarIndex + NumberOfBarsToProjectForward] = sc.Close[BarIndex]; } return; } /*==========================================================================*/ SCSFExport scsf_ArrayValueAtNthOccurrenceSample(SCStudyInterfaceRef sc) { SCSubgraphRef StochasticData = sc.Subgraph[0]; SCSubgraphRef ValueAtOccurence = sc.Subgraph[1]; SCSubgraphRef Line1 = sc.Subgraph[2]; SCInputRef KLength = sc.Input[3]; SCInputRef Line1Value = sc.Input[5]; SCInputRef MovAvgType = sc.Input[7]; SCInputRef InputDataHigh = sc.Input[8]; SCInputRef InputDataLow = sc.Input[9]; SCInputRef InputDataLast = sc.Input[10]; SCInputRef NumberOfOccurrences = sc.Input[11]; if (sc.SetDefaults) { sc.GraphName = "Array Value At Nth Occurrence Sample"; sc.StudyDescription = "Array Value At Nth Occurrence. Based on %K array of Fast Stochastic"; sc.ValueFormat = 2; StochasticData.Name = "%K"; StochasticData.DrawStyle = DRAWSTYLE_LINE; StochasticData.PrimaryColor = RGB(0,255,0); StochasticData.DrawZeros = true; ValueAtOccurence.Name = "Value At Nth Occurrence"; ValueAtOccurence.DrawStyle = DRAWSTYLE_LINE; ValueAtOccurence.PrimaryColor = RGB(255,0,255); ValueAtOccurence.DrawZeros = true; Line1.Name = "Line1"; Line1.DrawStyle = DRAWSTYLE_LINE; Line1.PrimaryColor = RGB(255,255,0); Line1.DrawZeros = true; KLength.Name = "%K Length"; KLength.SetInt(10); KLength.SetIntLimits(1,MAX_STUDY_LENGTH); Line1Value.Name = "Line1 Value"; Line1Value.SetFloat(70); MovAvgType.Name = "Moving Average Type"; MovAvgType.SetMovAvgType(MOVAVGTYPE_SIMPLE); InputDataHigh.Name = "Input Data"; InputDataHigh.SetInputDataIndex(SC_HIGH); InputDataLow.Name = "Input Data"; InputDataLow.SetInputDataIndex(SC_LOW); InputDataLast.Name = "Input Data"; InputDataLast.SetInputDataIndex(SC_LAST); NumberOfOccurrences.Name = "Number Of Occurrences"; NumberOfOccurrences.SetInt(10); NumberOfOccurrences.SetIntLimits(1,MAX_STUDY_LENGTH); sc.AutoLoop = true; return; } // This sample is based on Fast Stochastic Study. // The sample study use only %K subgraph // If %K value greater than Line1 value, then TRUE will be put to TrueFalse array, otherwise FALSE // The ValueAtOccurence Subgraph will have the values returned by sc.ArrayValueAtNthOccurrence function int InDLength = 3; sc.DataStartIndex = KLength.GetInt() + InDLength; sc.Stochastic(sc.BaseDataIn, sc.Subgraph[4], KLength.GetInt(), 1, 1, 1); sc.Stochastic( sc.BaseData[InputDataHigh.GetInputDataIndex()], sc.BaseData[InputDataLow.GetInputDataIndex()], sc.BaseData[InputDataLast.GetInputDataIndex()], StochasticData, KLength.GetInt(), InDLength, 0, MovAvgType.GetMovAvgType() ); // fill the TrueFalse array if (StochasticData[sc.Index] > Line1Value.GetFloat()) StochasticData.Arrays[1][sc.Index] = 1.0f; else StochasticData.Arrays[1][sc.Index] = 0.0f; ValueAtOccurence[sc.Index] = sc.ArrayValueAtNthOccurrence(StochasticData.Arrays[1], StochasticData, NumberOfOccurrences.GetInt()); Line1[sc.Index] = Line1Value.GetFloat(); } /*============================================================================*/ SCSFExport scsf_SwingHighAndLow(SCStudyInterfaceRef sc) { SCSubgraphRef SwingHigh = sc.Subgraph[0]; SCSubgraphRef SwingLow = sc.Subgraph[1]; SCSubgraphRef LinePropertiesSubgraph = sc.Subgraph[2]; SCInputRef ArrowOffsetValue = sc.Input[0]; SCInputRef Length = sc.Input[1]; SCInputRef AllowEqualBars = sc.Input[2]; SCInputRef ExtendSwings = sc.Input[3]; if (sc.SetDefaults) { sc.GraphName = "Swing High And Low"; sc.AutoLoop = true; sc.GraphRegion = 0; sc.ValueFormat= VALUEFORMAT_INHERITED; SwingHigh.Name = "Swing High"; SwingHigh.DrawStyle = DRAWSTYLE_ARROW_DOWN; SwingHigh.PrimaryColor = RGB(0,255,0); SwingHigh.DrawZeros = false; SwingHigh.PrimaryColor = RGB(255,0,0); SwingHigh.LineWidth = 3; SwingLow.Name = "Swing Low"; SwingLow.DrawStyle = DRAWSTYLE_ARROW_UP; SwingLow.PrimaryColor = RGB(255,0,255); SwingLow.DrawZeros = false; SwingLow.LineWidth = 3; SwingLow.PrimaryColor = RGB(0,255,0); LinePropertiesSubgraph.Name = "Line Properties"; LinePropertiesSubgraph.DrawStyle = DRAWSTYLE_SUBGRAPH_NAME_AND_VALUE_LABELS_ONLY; LinePropertiesSubgraph.LineWidth = 1; LinePropertiesSubgraph.PrimaryColor = RGB(255, 0, 0); LinePropertiesSubgraph.SecondaryColor = RGB(0, 255, 0); LinePropertiesSubgraph.SecondaryColorUsed = true; LinePropertiesSubgraph.DrawZeros = false; ArrowOffsetValue.Name = "Arrow Offset as Percentage"; ArrowOffsetValue.SetFloat(3); Length.Name = "Length"; Length.SetInt(1); Length.SetIntLimits(1,MAX_STUDY_LENGTH); AllowEqualBars.Name = "Allow Equal High/Low Bars"; AllowEqualBars.SetYesNo(false); ExtendSwings.Name = "Extend Swings Until Future Intersection"; ExtendSwings.SetYesNo(false); return; } int IndexToEvaluate = sc.Index - Length.GetInt(); if(IndexToEvaluate - Length.GetInt() < 0) { return; } sc.EarliestUpdateSubgraphDataArrayIndex = IndexToEvaluate; float ArrowOffset=(sc.High[IndexToEvaluate] - sc.Low[IndexToEvaluate] )*(ArrowOffsetValue.GetFloat() * 0.01f); SwingHigh[IndexToEvaluate] = 0; SwingLow[IndexToEvaluate] = 0; // check for Swing High if (!AllowEqualBars.GetYesNo()) { if (sc.IsSwingHigh(sc.High, IndexToEvaluate, Length.GetInt())) SwingHigh[IndexToEvaluate] = sc.High[IndexToEvaluate] + ArrowOffset; } else if (IsSwingHighAllowEqual_S( sc, true , IndexToEvaluate, Length.GetInt())) SwingHigh[IndexToEvaluate] = sc.High[IndexToEvaluate] + ArrowOffset; // check for Swing Low if (!AllowEqualBars.GetYesNo()) { if (sc.IsSwingLow(sc.Low, IndexToEvaluate, Length.GetInt())) SwingLow[IndexToEvaluate] = sc.Low[IndexToEvaluate] - ArrowOffset; } else if (IsSwingLowAllowEqual_S(sc, true , IndexToEvaluate, Length.GetInt())) SwingLow[IndexToEvaluate] = sc.Low[IndexToEvaluate] - ArrowOffset; if (ExtendSwings.GetYesNo() && SwingHigh[IndexToEvaluate] != 0) { sc.AddLineUntilFutureIntersection ( IndexToEvaluate , 1 // LineIDForBar , SwingHigh[IndexToEvaluate] , LinePropertiesSubgraph.PrimaryColor , LinePropertiesSubgraph.LineWidth , LinePropertiesSubgraph.LineStyle , false , false , "" ); } if (ExtendSwings.GetYesNo() && SwingLow[IndexToEvaluate] != 0) { sc.AddLineUntilFutureIntersection ( IndexToEvaluate , 2 // LineIDForBar , SwingLow[IndexToEvaluate] , LinePropertiesSubgraph.SecondaryColor , LinePropertiesSubgraph.LineWidth , LinePropertiesSubgraph.LineStyle , false , false , "" ); } } /******************************************************************************************/ SCSFExport scsf_ForceIndexAverage(SCStudyInterfaceRef sc) { // Section 1 - Set the configuration variables SCSubgraphRef ForceAverage = sc.Subgraph[0]; SCFloatArrayRef ForceIndex = sc.Subgraph[0].Arrays[0]; SCInputRef AverageLength = sc.Input[0]; if (sc.SetDefaults) { // Set the configuration and defaults sc.GraphName = "Force Index Average"; sc.StudyDescription = ""; sc.AutoLoop = 1; sc.ValueFormat = 2; sc.GraphRegion = 1; ForceAverage.Name = "Force Average"; ForceAverage.DrawStyle = DRAWSTYLE_LINE; ForceAverage.PrimaryColor = RGB(0,255,0); ForceAverage.DrawZeros = true; AverageLength.Name = "Moving Average Length"; AverageLength.SetInt(20); AverageLength.SetIntLimits(1, MAX_STUDY_LENGTH); return; } // Section 2 - Do data processing here sc.DataStartIndex = AverageLength.GetInt(); int i = sc.Index; ForceIndex[i] = sc.Volume[i] * (sc.Close[i] - sc.Close[i-1]); sc.ExponentialMovAvg(ForceIndex,ForceAverage,AverageLength.GetInt()); } /******************************************************************************************/ SCSFExport scsf_ForceIndex(SCStudyInterfaceRef sc) { // Section 1 - Set the configuration variables SCSubgraphRef ForceIndex = sc.Subgraph[0]; if (sc.SetDefaults) { // Set the configuration and defaults sc.GraphName = "Force Index"; sc.StudyDescription = ""; sc.AutoLoop = 1; sc.ValueFormat = 2; sc.GraphRegion = 1; ForceIndex.Name = "Force Average"; ForceIndex.DrawStyle = DRAWSTYLE_LINE; ForceIndex.PrimaryColor = RGB(0,255,0); ForceIndex.DrawZeros = true; return; } // Section 2 - Do data processing here int i = sc.Index; ForceIndex[i] = sc.Volume[i] * (sc.Close[i] - sc.Close[i-1]); } /******************************************************************************************/ /******************************************************************** * * True Strength Index (Also known as Ergodic) * * Array 3-8 are used for calculations * * Numerator = EMA( EMA(Price - LastPrice, LongExpMALength), ShortExpMALength) * Denominator = EMA( EMA( Abs(Price - LastPrice), LongExpMALength), ShortExpMaLength) * * TSI = Multiplier * Numerator / Denominator * SignalMA = EMA(TSI, SignalMALength) * Oscillator = TSI - SignalMA * *********************************************************************/ SCSFExport scsf_TrueStrengthIndex(SCStudyInterfaceRef sc) { SCSubgraphRef TSI = sc.Subgraph[0]; SCSubgraphRef SignalMA = sc.Subgraph[1]; SCSubgraphRef Oscillator = sc.Subgraph[2]; SCSubgraphRef Temp3 = sc.Subgraph[3]; SCSubgraphRef Temp4 = sc.Subgraph[4]; SCSubgraphRef Temp5 = sc.Subgraph[5]; SCSubgraphRef Temp6 = sc.Subgraph[6]; SCSubgraphRef Temp7 = sc.Subgraph[7]; SCSubgraphRef Temp8 = sc.Subgraph[8]; SCInputRef InputData = sc.Input[0]; SCInputRef LongExpMALength = sc.Input[3]; SCInputRef ShortExpMALength = sc.Input[4]; SCInputRef Multiplier = sc.Input[5]; SCInputRef SignalLineMALength = sc.Input[6]; if (sc.SetDefaults) { sc.GraphName = "True Strength Index"; sc.GraphRegion = 1; sc.ValueFormat = 2; sc.AutoLoop = 1; TSI.Name = "TSI"; TSI.DrawStyle = DRAWSTYLE_LINE; TSI.PrimaryColor = RGB(0,255,0); TSI.DrawZeros = false; SignalMA.Name = "Signal MA"; SignalMA.DrawStyle = DRAWSTYLE_HIDDEN; SignalMA.PrimaryColor = RGB(255,0,255); SignalMA.DrawZeros = false; Oscillator.Name = "Oscillator"; Oscillator.DrawStyle = DRAWSTYLE_HIDDEN; Oscillator.PrimaryColor = RGB(255,255,0); Oscillator.DrawZeros = false; InputData.Name = "Input Data"; InputData.SetInputDataIndex(SC_LAST); LongExpMALength.Name = "Long Exp MovAvg Length"; LongExpMALength.SetInt(15); LongExpMALength.SetIntLimits(1, MAX_STUDY_LENGTH); ShortExpMALength.Name = "Short Exp MovAvg Length"; ShortExpMALength.SetInt(5); ShortExpMALength.SetIntLimits(1, MAX_STUDY_LENGTH); Multiplier.Name = "Multiplier"; Multiplier.SetInt(1); SignalLineMALength.Name = "Signal Line MovAvg Length"; SignalLineMALength.SetInt(10); SignalLineMALength.SetIntLimits(1, MAX_STUDY_LENGTH); return; } // Subgraphs 3-7 are used for calculation only sc.DataStartIndex = ((LongExpMALength.GetInt() ) + (ShortExpMALength.GetInt()) + SignalLineMALength.GetInt()) ; if (sc.Index < 1) // not large enough return; int LongStart = sc.Index; if (LongStart < LongExpMALength.GetInt() - 1) //2 LongStart = LongExpMALength.GetInt() - 1; //2 int ShortStart = sc.Index; if (ShortStart < LongExpMALength.GetInt() - 1 + ShortExpMALength.GetInt() - 1) //3 ShortStart = LongExpMALength.GetInt() - 1 + ShortExpMALength.GetInt() - 1; //3 int SignalStart = sc.Index; if (SignalStart < ShortExpMALength.GetInt() - 1 + SignalLineMALength.GetInt() - 1+LongExpMALength.GetInt() -1) //4 SignalStart = ShortExpMALength.GetInt() - 1 + SignalLineMALength.GetInt() - 1 +LongExpMALength.GetInt() -1; //4 int DataStart = sc.Index; if (DataStart < 1) DataStart = 1; if(sc.Index >= DataStart) Temp3[sc.Index] = sc.BaseDataIn[InputData.GetInputDataIndex()][sc.Index] - sc.BaseDataIn[InputData.GetInputDataIndex()][sc.Index-1]; // Calculate the Numerator into SubGraphData[0] if(sc.Index >= LongStart) sc.MovingAverage(Temp3, Temp4, MOVAVGTYPE_EXPONENTIAL, LongExpMALength.GetInt()); if(sc.Index >= ShortStart) sc.MovingAverage(Temp4, Temp5, MOVAVGTYPE_EXPONENTIAL, ShortExpMALength.GetInt()); // Calculate the Denominator into SubGraphData[1] if(sc.Index >= DataStart) Temp6[sc.Index] = fabs(Temp3[sc.Index]); if(sc.Index >= LongStart) sc.MovingAverage(Temp6, Temp7, MOVAVGTYPE_EXPONENTIAL, LongExpMALength.GetInt()); if(sc.Index >= ShortStart) { sc.MovingAverage(Temp7, Temp8, MOVAVGTYPE_EXPONENTIAL, ShortExpMALength.GetInt()); // Store the TSI (Numerator / Denominator) if (Temp8[sc.Index] != 0) TSI[sc.Index] = Multiplier.GetInt() * Temp5[sc.Index]/Temp8[sc.Index]; else TSI[sc.Index] = 0; } // Calculate the Signal Line ( EMA[TSI] ) if(sc.Index >= SignalStart) sc.MovingAverage(TSI, SignalMA, MOVAVGTYPE_EXPONENTIAL, SignalLineMALength.GetInt()); // Calculate the Oscillator (TSI - EMA[TSI]) if(sc.Index >= sc.DataStartIndex) Oscillator[sc.Index] = TSI[sc.Index] - SignalMA[sc.Index]; } /*============================================================================*/ SCSFExport scsf_CommodityChannelIndex(SCStudyInterfaceRef sc) { SCInputRef I_InputData = sc.Input[0]; SCInputRef I_Length = sc.Input[3]; SCInputRef I_Multiplier = sc.Input[4]; SCInputRef I_Line2Value = sc.Input[5]; SCInputRef I_Line3Value = sc.Input[6]; SCInputRef I_MAType = sc.Input[7]; SCInputRef I_Version = sc.Input[8]; SCSubgraphRef CCI = sc.Subgraph[0]; SCSubgraphRef Line1 = sc.Subgraph[1]; SCSubgraphRef Line2 = sc.Subgraph[2]; SCSubgraphRef Line3 = sc.Subgraph[3]; if (sc.SetDefaults) { // Set the configuration and defaults sc.GraphName = "Commodity Channel Index"; sc.AutoLoop = 1; // true sc.GraphRegion = 1; sc.ValueFormat = 2; CCI.Name = "CCI"; CCI.DrawStyle = DRAWSTYLE_BAR; CCI.PrimaryColor = RGB(0,255,0); CCI.DrawZeros= true; Line1.Name = "Line 1"; Line1.DrawStyle = DRAWSTYLE_HIDDEN; Line1.PrimaryColor = RGB(255,0,255); Line1.DrawZeros= true; Line2.Name = "Line 2"; Line2.DrawStyle = DRAWSTYLE_LINE; Line2.PrimaryColor = RGB(255,255,0); Line2.DrawZeros = false; Line3.Name = "Line 3"; Line3.DrawStyle = DRAWSTYLE_LINE; Line3.PrimaryColor = RGB(255,127,0); Line3.DrawZeros = false; I_InputData.Name = "Input Data"; I_InputData.SetInputDataIndex(SC_HLC_AVG); I_Length.Name = "Length"; I_Length.SetInt(10); I_Length.SetIntLimits(1,MAX_STUDY_LENGTH); I_Multiplier.Name = "Multiplier"; I_Multiplier.SetFloat(0.015f); I_Line2Value.Name = "Line2 Value"; I_Line2Value.SetFloat(100); I_Line3Value.Name = "Line3 Value"; I_Line3Value.SetFloat(-100); I_MAType.Name = "Moving Average Type"; I_MAType.SetMovAvgType(MOVAVGTYPE_SIMPLE); I_Version.SetInt(1); return; } if(I_Version.GetInt() < 1) { I_Version.SetInt(1); I_MAType.SetMovAvgType(MOVAVGTYPE_SIMPLE); } sc.DataStartIndex = I_Length.GetInt(); float Multiplier = I_Multiplier.GetFloat(); if(Multiplier == 0.0f) Multiplier = 0.015f; sc.CCI(sc.BaseDataIn[I_InputData.GetInputDataIndex()], CCI, sc.Index, I_Length.GetInt(), Multiplier, I_MAType.GetMovAvgType()); Line2[sc.Index] = I_Line2Value.GetFloat(); Line3[sc.Index] = I_Line3Value.GetFloat(); } /*============================================================================*/ SCSFExport scsf_TradeVolumeIndex(SCStudyInterfaceRef sc) { SCSubgraphRef TVI = sc.Subgraph[0]; SCInputRef InputData = sc.Input[0]; if (sc.SetDefaults) { sc.GraphName = "Trade Volume Index"; sc.ValueFormat = 0; sc.GraphRegion = 1; sc.AutoLoop = 1; TVI.Name = "TVI"; TVI.DrawStyle = DRAWSTYLE_LINE; TVI.PrimaryColor = RGB(0,255,0); TVI.DrawZeros = true; InputData.Name = "Input Data"; InputData.SetInputDataIndex(SC_LAST); return; } sc.DataStartIndex = 1; if(sc.Index < 1) return; int Index = sc.Index; float Diff = sc.BaseDataIn[InputData.GetInputDataIndex()][Index] - sc.BaseDataIn[InputData.GetInputDataIndex()][Index-1]; if(sc.FormattedEvaluate((float) Diff,sc.BaseGraphValueFormat,GREATER_OPERATOR,sc.TickSize ,sc.BaseGraphValueFormat) != 0) TVI[Index] = TVI[Index-1] + sc.Volume[Index]; else if(sc.FormattedEvaluate((float) Diff,sc.BaseGraphValueFormat,LESS_OPERATOR,sc.TickSize*-1 ,sc.BaseGraphValueFormat) != 0) TVI[Index] = TVI[Index-1] - sc.Volume[Index]; else TVI[Index] = TVI[Index-1]; } /************************************************************** * * Demand Index * * Array Number Usage * * Array 0 - Demand Index * Array 1 - Demand Index Moving Average * Array 2 - Zero Line * Array 3 - Moving Average Sell Power * Array 4 - High + Low + 2 * Last * Array 5 - Max of last 2 High's - Min of last 2 Low's * Array 6 - EMA of Array 5 * Array 7 - EMA of Volume * Array 8 - BuyPower * Array 9 - SellPower * Array 10 - Moving Average Buy Power * ***************************************************************/ SCSFExport scsf_DemandIndex(SCStudyInterfaceRef sc) { SCSubgraphRef OutDemandIndex = sc.Subgraph[0]; // Demand Index SCSubgraphRef OutDemandIndexMA = sc.Subgraph[1]; // Demand Index Moving Average SCSubgraphRef OutZeroLine = sc.Subgraph[2]; // Zero Line SCFloatArrayRef ArrHL2C = sc.Subgraph[0].Arrays[0]; // High + Low + 2 * Last SCFloatArrayRef ArrRange = sc.Subgraph[0].Arrays[1]; // Max of last 2 High's - Min of last 2 Low's SCFloatArrayRef ArrRangeMA = sc.Subgraph[1].Arrays[1]; // EMA of Array 5 SCFloatArrayRef ArrVolumeMA = sc.Subgraph[1].Arrays[0]; // EMA of Volume SCFloatArrayRef ArrBuyPower = sc.Subgraph[0].Arrays[2]; // BuyPower SCFloatArrayRef ArrSellPower = sc.Subgraph[0].Arrays[3]; // SellPower SCFloatArrayRef ArrMABuyPower = sc.Subgraph[1].Arrays[2]; // Moving Average Buy Power SCFloatArrayRef ArrMASellPower = sc.Subgraph[1].Arrays[3]; // Moving Average Sell Power SCInputRef BSPowerLength = sc.Input[0]; SCInputRef BSPowerMovAvgLength = sc.Input[1]; SCInputRef DIMovAvgLength = sc.Input[2]; SCInputRef DIMovAvgType = sc.Input[3]; if (sc.SetDefaults) { sc.GraphName = "Demand Index"; sc.AutoLoop = 1; OutDemandIndex.Name = "DI"; OutDemandIndex.PrimaryColor = RGB(0,255,0); OutDemandIndex.DrawStyle = DRAWSTYLE_LINE; OutDemandIndex.LineWidth = 1; OutDemandIndex.DrawZeros = true; OutDemandIndexMA.Name = "DI MovAvg"; OutDemandIndexMA.PrimaryColor = RGB(255,125,125); OutDemandIndexMA.DrawStyle = DRAWSTYLE_LINE; OutDemandIndexMA.LineWidth = 1; OutDemandIndexMA.DrawZeros = true; OutZeroLine.Name = "Line"; OutZeroLine.PrimaryColor = RGB(125,125,125); OutZeroLine.DrawStyle = DRAWSTYLE_LINE; OutZeroLine.LineWidth = 1; OutZeroLine.DrawZeros = true; BSPowerLength.Name = "Buy/Sell Power Length"; BSPowerLength.SetInt(19); BSPowerLength.SetIntLimits(1, 100); BSPowerMovAvgLength.Name = "Buy/Sell Power Moving Average Length"; BSPowerMovAvgLength.SetInt(19); BSPowerMovAvgLength.SetIntLimits(1, 100); DIMovAvgLength.Name = "Demand Index Moving Average Length"; DIMovAvgLength.SetInt(30); DIMovAvgLength.SetIntLimits(1, 100); DIMovAvgType.Name = "Demand Index Moving Average Type"; DIMovAvgType.SetMovAvgType(MOVAVGTYPE_EXPONENTIAL); return; } ArrHL2C[sc.Index] = sc.High[sc.Index] + sc.Low[sc.Index] + 2 * sc.Close[sc.Index]; if (sc.Index == 0) { ArrRange[0] = sc.High[0] - sc.Low[0]; } else { ArrRange[sc.Index] = max(sc.High[sc.Index], sc.High[sc.Index - 1]) - min(sc.Low[sc.Index], sc.Low[sc.Index - 1]); } // sc.MovingAverage(ArrRange, ArrRangeMA, DIMovAvgType.GetMovAvgType(), BSPowerLength.GetInt()); sc.MovingAverage(sc.Volume, ArrVolumeMA, DIMovAvgType.GetMovAvgType(), BSPowerLength.GetInt()); // if (sc.Index >= 1) { ArrBuyPower[sc.Index] = sc.Volume[sc.Index] / ArrVolumeMA[sc.Index]; ArrSellPower[sc.Index] = sc.Volume[sc.Index] / ArrVolumeMA[sc.Index]; if (ArrHL2C[sc.Index] < ArrHL2C[sc.Index - 1]) { ArrBuyPower[sc.Index] = ArrBuyPower[sc.Index] / exp( ( 0.375f * (ArrHL2C[sc.Index] + ArrHL2C[sc.Index - 1]) / ArrRangeMA[0] ) * (ArrHL2C[sc.Index - 1] - ArrHL2C[sc.Index]) / ArrHL2C[sc.Index] ); } else if (ArrHL2C[sc.Index] > ArrHL2C[sc.Index - 1]) { ArrSellPower[sc.Index] = ArrSellPower[sc.Index] / exp( ( 0.375f * (ArrHL2C[sc.Index] + ArrHL2C[sc.Index - 1]) / ArrRangeMA[0] ) * (ArrHL2C[sc.Index] - ArrHL2C[sc.Index - 1]) / ArrHL2C[sc.Index - 1] ); } } // sc.MovingAverage(ArrBuyPower, ArrMABuyPower, DIMovAvgType.GetMovAvgType(), BSPowerMovAvgLength.GetInt()); sc.MovingAverage(ArrSellPower, ArrMASellPower, DIMovAvgType.GetMovAvgType(), BSPowerMovAvgLength.GetInt()); // float divsor, divend; if (ArrMABuyPower[sc.Index] > ArrMASellPower[sc.Index]) { divsor = ArrMABuyPower[sc.Index]; divend = ArrMASellPower[sc.Index]; } else if (ArrMABuyPower[sc.Index] < ArrMASellPower[sc.Index]) { divsor = ArrMASellPower[sc.Index]; divend = ArrMABuyPower[sc.Index]; } else { divsor = ArrMASellPower[sc.Index]; divend = ArrMASellPower[sc.Index]; } float var2 = 1 - (divend/divsor); float var3 = var2; if (ArrMASellPower[sc.Index] > ArrMABuyPower[sc.Index]) var3 *= -1; OutDemandIndex[sc.Index] = var3 * 100; OutZeroLine[sc.Index] = 0; // sc.MovingAverage(OutDemandIndex, OutDemandIndexMA, MOVAVGTYPE_SIMPLE, DIMovAvgLength.GetInt()); } /*============================================================================*/ SCSFExport scsf_BollingerBandBandwidth(SCStudyInterfaceRef sc) { SCSubgraphRef BBBandWidth = sc.Subgraph[0]; SCSubgraphRef OutBollingerBands = sc.Subgraph[1]; SCInputRef InputData = sc.Input[0]; SCInputRef MovingAverageType = sc.Input[1]; SCInputRef Length = sc.Input[3]; SCInputRef StandardDeviations = sc.Input[4]; SCInputRef Version = sc.Input[5]; if (sc.SetDefaults) { sc.GraphName = "Bollinger Bands: Bandwidth"; sc.ValueFormat = 3; sc.GraphRegion = 1; sc.AutoLoop = 1; BBBandWidth.Name = "BollingerBands: Bandwidth"; BBBandWidth.DrawStyle = DRAWSTYLE_LINE; BBBandWidth.PrimaryColor = RGB(0,255,0); BBBandWidth.DrawZeros = true; InputData.Name = "Input Data"; InputData.SetInputDataIndex(SC_HLC_AVG); MovingAverageType.Name = "Moving Average Type"; MovingAverageType.SetMovAvgType(MOVAVGTYPE_SIMPLE); Length.Name = "Length"; Length.SetInt(5); Length.SetIntLimits(1,MAX_STUDY_LENGTH); StandardDeviations.Name = "Standard Deviations"; StandardDeviations.SetFloat(2.0f); StandardDeviations.SetFloatLimits(0.00001f,(float)MAX_STUDY_LENGTH); Version.SetInt(1); return; } if (Version.GetInt() < 1) { MovingAverageType.SetMovAvgType(MOVAVGTYPE_SIMPLE); Version.SetInt(1); } int i = sc.Index; sc.DataStartIndex=Length.GetInt()-1; sc.BollingerBands(sc.BaseDataIn[InputData.GetInputDataIndex()], OutBollingerBands, Length.GetInt(), StandardDeviations.GetFloat(),MovingAverageType.GetMovAvgType()); SCFloatArrayRef MiddleBand = OutBollingerBands; SCFloatArrayRef UpperBand = OutBollingerBands.Arrays[0]; SCFloatArrayRef LowerBand = OutBollingerBands.Arrays[1]; BBBandWidth[i] = (UpperBand[i] - LowerBand[i]) / MiddleBand[i]; } /*============================================================================*/ SCSFExport scsf_BollingerBandsPercentB(SCStudyInterfaceRef sc) { SCSubgraphRef PercentB = sc.Subgraph[0]; SCSubgraphRef OutBollingerBands = sc.Subgraph[1]; SCSubgraphRef UpperThreshold = sc.Subgraph[2]; SCSubgraphRef LowerThreshold = sc.Subgraph[3]; SCInputRef InputData = sc.Input[0]; SCInputRef MovAvgType = sc.Input[1]; SCInputRef Length = sc.Input[3]; SCInputRef StandardDeviations = sc.Input[4]; SCInputRef BaseBand = sc.Input[5]; SCInputRef UpperThresholdValue = sc.Input[6]; SCInputRef LowerThresholdValue = sc.Input[7]; if (sc.SetDefaults) { sc.GraphName = "Bollinger Bands %B"; sc.ValueFormat = 3; sc.GraphRegion = 1; sc.AutoLoop = 1; PercentB.Name = "%B"; PercentB.DrawStyle = DRAWSTYLE_LINE; PercentB.PrimaryColor = RGB(0,255,0); PercentB.DrawZeros = true; UpperThreshold.Name = "Upper Threshold"; UpperThreshold.DrawStyle = DRAWSTYLE_LINE; UpperThreshold.LineStyle = LINESTYLE_DASH; UpperThreshold.PrimaryColor = COLOR_GRAY; UpperThreshold.DrawZeros = false; LowerThreshold.Name = "Lower Threshold"; LowerThreshold.DrawStyle = DRAWSTYLE_LINE; LowerThreshold.LineStyle = LINESTYLE_DASH; LowerThreshold.PrimaryColor = COLOR_GRAY; LowerThreshold.DrawZeros = false; InputData.Name = "Input Data"; InputData.SetInputDataIndex(SC_HLC_AVG); MovAvgType.Name = "Moving Average Type"; MovAvgType.SetMovAvgType(MOVAVGTYPE_SIMPLE); Length.Name = "Length"; Length.SetInt(10); Length.SetIntLimits(1, MAX_STUDY_LENGTH); StandardDeviations.Name = "Standard Deviations"; StandardDeviations.SetFloat(2.0f); BaseBand.Name = "Base Band"; BaseBand.SetCustomInputStrings( "Lower Band;Middle Band"); BaseBand.SetCustomInputIndex(0); UpperThresholdValue.Name = "Upper Line Threshold Value"; UpperThresholdValue.SetFloat(0); LowerThresholdValue.Name = "Lower Line Threshold Value"; LowerThresholdValue.SetFloat(0); return; } int Index = sc.Index; sc.DataStartIndex= Length.GetInt() -1; // Calculate Bollinger bands sc.BollingerBands(sc.BaseDataIn[InputData.GetInputDataIndex()], OutBollingerBands, Length.GetInt(), StandardDeviations.GetFloat(), MovAvgType.GetMovAvgType()); SCFloatArrayRef MiddleBand = OutBollingerBands; SCFloatArrayRef UpperBand = OutBollingerBands.Arrays[0]; SCFloatArrayRef LowerBand = OutBollingerBands.Arrays[1]; //Standard calculation: %B = (Price - Bottom Band)/(Top Band - Bottom Band) if (BaseBand.GetIndex()== 1) { float BandsDifference= UpperBand[Index] - MiddleBand[Index]; if(BandsDifference) PercentB[Index] = (sc.BaseDataIn[InputData.GetInputDataIndex()][Index] - MiddleBand[Index]) / BandsDifference; else PercentB[Index] = 0.0; } else { float BandsDifference= UpperBand[Index] - LowerBand[Index]; if(BandsDifference) PercentB[Index] = (sc.BaseDataIn[InputData.GetInputDataIndex()][Index] - LowerBand[Index]) / BandsDifference; else PercentB[Index] = 0.0; } UpperThreshold[Index] = UpperThresholdValue.GetFloat(); LowerThreshold[Index] = LowerThresholdValue.GetFloat(); } /*============================================================================*/ SCSFExport scsf_DifferenceBar(SCStudyInterfaceRef sc) { SCInputRef Chart2Number = sc.Input[3]; SCInputRef Chart1Multiplier = sc.Input[4]; SCInputRef Chart2Multiplier = sc.Input[5]; SCInputRef Chart1Addition = sc.Input[6]; SCInputRef ZeroOutputWhenNonExactDateTimeMatch = sc.Input[7]; SCInputRef UseLatestSourceDataForLastBar = sc.Input[8]; SCInputRef ZeroOutputWhenOneSourceGraphHasZeroValues = sc.Input[9]; if (sc.SetDefaults) { sc.GraphName = "Difference (Bar)"; sc.ValueFormat = VALUEFORMAT_INHERITED; sc.GraphRegion = 1; sc.GraphUsesChartColors = 1; sc.GraphDrawType = GDT_OHLCBAR; sc.StandardChartHeader = 1; // We are using Manual looping. sc.AutoLoop = false; for (int SubgraphIndex = 0; SubgraphIndex <= SC_ASKVOL; ++SubgraphIndex) { sc.Subgraph[SubgraphIndex].Name = sc.GetStudySubgraphName(0, SubgraphIndex); sc.Subgraph[SubgraphIndex].DrawZeros = false; if (SubgraphIndex < SC_VOLUME) sc.Subgraph[SubgraphIndex].DrawStyle = DRAWSTYLE_LINE; else sc.Subgraph[SubgraphIndex].DrawStyle = DRAWSTYLE_IGNORE; if (SubgraphIndex == SC_LAST) { sc.Subgraph[SubgraphIndex].LineLabel = LL_DISPLAY_VALUE | LL_VALUE_ALIGN_VALUES_SCALE | LL_VALUE_ALIGN_CENTER; } } Chart2Number.Name = "Chart 2 Number and Graph"; Chart2Number.SetChartStudyValues(1, 0); Chart1Multiplier.Name = "Chart 1 Multiplier"; Chart1Multiplier.SetFloat(1.0f); Chart2Multiplier.Name = "Chart 2 Multiplier"; Chart2Multiplier.SetFloat(1.0f); Chart1Addition.Name = "Chart 1 Addition"; Chart1Addition.SetFloat(0); ZeroOutputWhenNonExactDateTimeMatch.Name = "Zero Output When Non Exact Date-Time Match"; ZeroOutputWhenNonExactDateTimeMatch.SetYesNo(false); UseLatestSourceDataForLastBar.Name = "Use Latest Source Data For Last Bar"; UseLatestSourceDataForLastBar.SetYesNo(0); ZeroOutputWhenOneSourceGraphHasZeroValues.Name = "Zero Output When one Source Graph has Zero Values"; ZeroOutputWhenOneSourceGraphHasZeroValues.SetYesNo(0); return; } int LastProcessedSourceBarIndex = sc.GetPersistentInt(1); if (sc.IsFullRecalculation ) { // Create text indicating both charts and set to sc.GraphName SCString Chart1Name = sc.GetStudyNameFromChart(sc.ChartNumber, 0); SCString Chart2Name = sc.GetStudyNameFromChart(Chart2Number.GetChartNumber(), Chart2Number.GetStudyID()); sc.GraphName.Format("Difference %s * %g - %s * %g", Chart1Name.GetChars(), Chart1Multiplier.GetFloat(), Chart2Name.GetChars(), Chart2Multiplier.GetFloat()); LastProcessedSourceBarIndex = 0; } // Obtain a reference to the Base Data in the specified chart. This call is relatively efficient, but it should be called as minimally as possible. To reduce the number of calls we have it outside of the primary "for" loop in this study function. And we also use Manual Looping by using sc.AutoLoop = 0. In this way, sc.GetChartBaseData / sc.GetStudyArraysFromChartUsingID is called only once per call to this study function and there is a minimal number of calls to this study function. sc.GetChartBaseData is a function to get all of the Base Data arrays with one efficient call. SCGraphData Chart2BaseData; //sc.GetChartBaseData(-Chart2Number.GetChartNumber(), Chart2BaseData); sc.GetStudyArraysFromChartUsingID(-Chart2Number.GetChartNumber(), Chart2Number.GetStudyID(), Chart2BaseData); int CalculationStartIndex = sc.GetCalculationStartIndexForStudy(); if (!sc.IsFullRecalculation) { SCDateTimeArray Chart2DateTimeArray; sc.GetChartDateTimeArray(Chart2Number.GetChartNumber(), Chart2DateTimeArray); int DestinationStartIndex = sc.GetContainingIndexForSCDateTime(sc.ChartNumber, Chart2DateTimeArray[LastProcessedSourceBarIndex]); if (DestinationStartIndex < CalculationStartIndex) CalculationStartIndex = DestinationStartIndex; } for (int Index = CalculationStartIndex; Index < sc.ArraySize; Index++) { int Chart2Index = 0; if(ZeroOutputWhenNonExactDateTimeMatch.GetYesNo() == false) { Chart2Index = sc.GetNearestMatchForDateTimeIndex(Chart2Number.GetChartNumber(), Index); //When 'use latest source data for last bar' is set to Yes, replay is not running and at last bar in the destination chart, then use the data from the very latest bar in the source chart. if(UseLatestSourceDataForLastBar.GetYesNo() && !sc.IsReplayRunning() && Index == sc.ArraySize - 1) { Chart2Index = Chart2BaseData[0].GetArraySize() - 1; } LastProcessedSourceBarIndex = Chart2Index; } else { Chart2Index = sc.GetExactMatchForSCDateTime(Chart2Number.GetChartNumber(), sc.BaseDateTimeIn[Index]); LastProcessedSourceBarIndex = Chart2Index; if(Chart2Index == -1) { for (int SubgraphIndex = 0; SubgraphIndex <= SC_HL_AVG; SubgraphIndex++) { sc.Subgraph[SubgraphIndex][Index] = 0.0; } continue; } } if (ZeroOutputWhenOneSourceGraphHasZeroValues.GetYesNo()) { bool AllZeros = true; for (int SubgraphIndex = 0; SubgraphIndex <= SC_LAST; SubgraphIndex++) { if (Chart2BaseData[SubgraphIndex][Chart2Index] != 0) { AllZeros = false; break; } } if (AllZeros) continue; AllZeros = true; for (int SubgraphIndex = 0; SubgraphIndex <= SC_LAST; SubgraphIndex++) { if (sc.BaseDataIn[SubgraphIndex][Index] != 0) { AllZeros = false; break; } } if (AllZeros) continue; } for (int SubgraphIndex = 0; SubgraphIndex <= SC_NUM_TRADES; SubgraphIndex++) { sc.Subgraph[SubgraphIndex][Index] = (sc.BaseDataIn[SubgraphIndex][Index] * Chart1Multiplier.GetFloat() + Chart1Addition.GetFloat()) - (Chart2BaseData[SubgraphIndex][Chart2Index] * Chart2Multiplier.GetFloat()); } sc.Subgraph[SC_HIGH][Index] = max(sc.Subgraph[SC_OPEN][Index], max(sc.Subgraph[SC_HIGH][Index], max(sc.Subgraph[SC_LOW][Index],sc.Subgraph[SC_LAST][Index]) ) ); sc.Subgraph[SC_LOW][Index] = min(sc.Subgraph[SC_OPEN][Index], min(sc.Subgraph[SC_HIGH][Index], min(sc.Subgraph[SC_LOW][Index],sc.Subgraph[SC_LAST][Index]) ) ); sc.CalculateOHLCAverages(Index); } sc.EarliestUpdateSubgraphDataArrayIndex = CalculationStartIndex; } /*============================================================================*/ SCSFExport scsf_DifferenceBidAskPrices(SCStudyInterfaceRef sc) { SCSubgraphRef Subgraph_BidPrice = sc.Subgraph[0]; SCSubgraphRef Subgraph_AskPrice = sc.Subgraph[1]; SCInputRef Chart2Number = sc.Input[3]; SCInputRef Chart1Multiplier = sc.Input[4]; SCInputRef Chart2Multiplier = sc.Input[5]; SCInputRef Chart1Addition = sc.Input[6]; SCInputRef ZeroOutputWhenNonExactDateTimeMatch = sc.Input[7]; SCInputRef UseLatestSourceDataForLastBar = sc.Input[8]; SCInputRef ZeroOutputWhenOneSourceGraphHasZeroValues = sc.Input[9]; if (sc.SetDefaults) { sc.GraphName = "Difference (Bid and Ask Prices)"; sc.ValueFormat = VALUEFORMAT_INHERITED; sc.GraphRegion = 1; sc.MaintainAdditionalChartDataArrays = true;// needed to maintain bid and ask arrays in the base graph // Using Manual looping. sc.AutoLoop = false; Subgraph_BidPrice.Name = "Bid"; Subgraph_BidPrice.DrawZeros = false; Subgraph_BidPrice.DrawStyle = DRAWSTYLE_LINE; Subgraph_BidPrice.LineWidth = 2; Subgraph_BidPrice.LineLabel = LL_DISPLAY_VALUE | LL_VALUE_ALIGN_VALUES_SCALE | LL_VALUE_ALIGN_CENTER; Subgraph_AskPrice.Name = "Ask"; Subgraph_AskPrice.DrawZeros = false; Subgraph_AskPrice.DrawStyle = DRAWSTYLE_LINE; Subgraph_AskPrice.LineWidth = 2; Subgraph_AskPrice.LineLabel = LL_DISPLAY_VALUE | LL_VALUE_ALIGN_VALUES_SCALE | LL_VALUE_ALIGN_CENTER; Chart2Number.Name = "Chart 2 Number and Graph"; Chart2Number.SetChartStudyValues(1, 0); Chart1Multiplier.Name = "Chart 1 Multiplier"; Chart1Multiplier.SetFloat(1.0f); Chart2Multiplier.Name = "Chart 2 Multiplier"; Chart2Multiplier.SetFloat(1.0f); Chart1Addition.Name = "Chart 1 Addition"; Chart1Addition.SetFloat(0); ZeroOutputWhenNonExactDateTimeMatch.Name = "Zero Output When Non Exact Date-Time Match"; ZeroOutputWhenNonExactDateTimeMatch.SetYesNo(false); UseLatestSourceDataForLastBar.Name = "Use Latest Source Data For Last Bar"; UseLatestSourceDataForLastBar.SetYesNo(0); ZeroOutputWhenOneSourceGraphHasZeroValues.Name = "Zero Output When one Source Graph has Zero Values"; ZeroOutputWhenOneSourceGraphHasZeroValues.SetYesNo(0); return; } if (sc.IsFullRecalculation) { // Create text indicating both charts and set to sc.GraphName SCString Chart1Name = sc.GetStudyNameFromChart(sc.ChartNumber, 0); SCString Chart2Name = sc.GetStudyNameFromChart(Chart2Number.GetChartNumber(), Chart2Number.GetStudyID()); sc.GraphName.Format("Difference %s * %g - %s * %g", Chart1Name.GetChars(), Chart1Multiplier.GetFloat(), Chart2Name.GetChars(), Chart2Multiplier.GetFloat()); } // Obtain a reference to the Base Data in the specified chart. SCGraphData Chart2BaseData; sc.GetStudyArraysFromChartUsingID(-Chart2Number.GetChartNumber(), Chart2Number.GetStudyID(), Chart2BaseData); int CalculationStartIndex = sc.GetCalculationStartIndexForStudy(); for (int Index = CalculationStartIndex; Index < sc.ArraySize; Index++) { int Chart2Index = 0; if (ZeroOutputWhenNonExactDateTimeMatch.GetYesNo() == false) { Chart2Index = sc.GetNearestMatchForDateTimeIndex(Chart2Number.GetChartNumber(), Index); //When 'use latest source data for last bar' is set to Yes, replay is not running and at last bar in the destination chart, then use the data from the very latest bar in the source chart. if (UseLatestSourceDataForLastBar.GetYesNo() && !sc.IsReplayRunning() && Index == sc.ArraySize - 1) Chart2Index = Chart2BaseData[0].GetArraySize() - 1; } else { Chart2Index = sc.GetExactMatchForSCDateTime(Chart2Number.GetChartNumber(), sc.BaseDateTimeIn[Index]); if (Chart2Index == -1) { Subgraph_BidPrice[Index] = 0; Subgraph_AskPrice[Index] = 0; continue; } } if (ZeroOutputWhenOneSourceGraphHasZeroValues.GetYesNo()) { bool AllZeros = true; for (int SubgraphIndex = SC_BID_PRICE; SubgraphIndex <= SC_ASK_PRICE; SubgraphIndex++) { if (Chart2BaseData[SubgraphIndex][Chart2Index] != 0) { AllZeros = false; break; } } if (AllZeros) continue; for (int SubgraphIndex = SC_BID_PRICE; SubgraphIndex <= SC_ASK_PRICE; SubgraphIndex++) { if (sc.BaseDataIn[SubgraphIndex][Index] != 0) { AllZeros = false; break; } } if (AllZeros) continue; } for (int SubgraphIndex = 0; SubgraphIndex <= 1; SubgraphIndex++) { sc.Subgraph[SubgraphIndex][Index] = (sc.BaseDataIn[SubgraphIndex == 0 ? SC_BID_PRICE : SC_ASK_PRICE][Index] * Chart1Multiplier.GetFloat() + Chart1Addition.GetFloat()) - (Chart2BaseData[SubgraphIndex == 0 ? SC_BID_PRICE : SC_ASK_PRICE][Chart2Index] * Chart2Multiplier.GetFloat()); } } sc.EarliestUpdateSubgraphDataArrayIndex = CalculationStartIndex; } /*============================================================================*/ SCSFExport scsf_HighLowForTimePeriodExtendedLines(SCStudyInterfaceRef sc) { SCSubgraphRef HighOfDay = sc.Subgraph[0]; SCSubgraphRef LowOfDay = sc.Subgraph[1]; SCInputRef Input_StartTime = sc.Input[0]; SCInputRef Input_EndTime = sc.Input[1]; SCInputRef Input_NumberDaysToCalculate = sc.Input[2]; SCInputRef Input_Version = sc.Input[4]; SCInputRef Input_LineStopTimeInput = sc.Input[5]; SCInputRef Input_DisplayHighLowIncrementally = sc.Input[6]; SCInputRef Input_InputDataHigh = sc.Input[7]; SCInputRef Input_InputDataLow = sc.Input[8]; SCInputRef Input_FridayEveningExtendsIntoSunday = sc.Input[9]; if (sc.SetDefaults) { sc.GraphName = "High/Low for Time Period - Extended"; sc.GraphRegion = 0; sc.AutoLoop = 0; HighOfDay.Name = "High"; HighOfDay.DrawStyle = DRAWSTYLE_STAIR_STEP; HighOfDay.PrimaryColor = RGB(0,255,0); HighOfDay. DrawZeros = false; LowOfDay.Name = "Low"; LowOfDay.DrawStyle = DRAWSTYLE_STAIR_STEP; LowOfDay.PrimaryColor = RGB(255,0,255); LowOfDay.DrawZeros = false; Input_StartTime.Name = "Start Time"; Input_StartTime.SetTime(0); Input_EndTime.Name = "End Time"; Input_EndTime.SetTime(SECONDS_PER_DAY - 1); Input_NumberDaysToCalculate.Name= "Number Of Days To Calculate"; Input_NumberDaysToCalculate.SetInt(120); Input_LineStopTimeInput.Name = "Line Stop Time"; Input_LineStopTimeInput.SetTime(SECONDS_PER_DAY - 1); Input_DisplayHighLowIncrementally.Name = "Display High Low Incrementally"; Input_DisplayHighLowIncrementally.SetYesNo( true); Input_InputDataHigh.Name = "Input Data High"; Input_InputDataHigh.SetInputDataIndex(SC_HIGH); Input_InputDataLow.Name = "Input Data Low"; Input_InputDataLow.SetInputDataIndex(SC_LOW); Input_FridayEveningExtendsIntoSunday.Name = "Friday Evening Extends Into Sunday"; Input_FridayEveningExtendsIntoSunday.SetYesNo(false); Input_Version.SetInt(3); return; } if (Input_Version.GetInt() == 1) { Input_InputDataHigh.SetInputDataIndex(SC_HIGH); Input_InputDataLow.SetInputDataIndex(SC_LOW); Input_Version.SetInt(2); } if (Input_Version.GetInt() <= 2) { Input_LineStopTimeInput.SetTime(sc.EndTime1); Input_Version.SetInt(3); } if (Input_NumberDaysToCalculate.GetInt() <= 0) Input_NumberDaysToCalculate.SetInt(10000); //if (Input_StartTime.GetTime() <= Input_EndTime.GetTime() // // && (Input_StartTime.GetTime() < sc.StartTimeOfDay && Input_EndTime.GetTime() > sc.StartTimeOfDay) // ) //{ // Input_StartTime.SetTime(sc.StartTimeOfDay); // //Check if the start time is now greater than or equal to the end time in which case move the end time forward by 30 minutes from the start time. // if (Input_StartTime.GetTime() >= Input_EndTime.GetTime()) // { // Input_EndTime.SetTime(Input_StartTime.GetTime() + 30 * 60); // } //} float & HighOfPeriod = sc.GetPersistentFloat(1); float & LowOfPeriod = sc.GetPersistentFloat(2); SCDateTime DaysToCalculateStartDateTime = sc.GetTradingDayStartDateTimeOfBar(sc.BaseDateTimeIn[sc.ArraySize - 1]) - (Input_NumberDaysToCalculate.GetInt() - 1); // Loop through chart bars starting at the Update Start Index for (int Index = sc.UpdateStartIndex; Index < sc.ArraySize; Index++ ) { const SCDateTime CurrentBarDateTime = sc.BaseDateTimeIn[Index]; const SCDateTime PreviousBarDateTime = sc.BaseDateTimeIn[max(0, Index - 1)]; SCDateTime ResetTime; ResetTime.SetTime(Input_LineStopTimeInput.GetTime()); bool NeedReset = (PreviousBarDateTime.GetTimeInSeconds() < ResetTime.GetTimeInSeconds() && CurrentBarDateTime.GetTimeInSeconds() >= ResetTime.GetTimeInSeconds()) || (PreviousBarDateTime.GetTimeInSeconds() < ResetTime.GetTimeInSeconds() && CurrentBarDateTime.GetTimeInSeconds() < ResetTime.GetTimeInSeconds() && PreviousBarDateTime.GetDate() != CurrentBarDateTime.GetDate()); NeedReset |= Index == 0; if (sc.BaseDateTimeIn[Index] < DaysToCalculateStartDateTime) continue; SCDateTime StartDateTime; SCDateTime EndDateTime; StartDateTime = CurrentBarDateTime.GetDate(); EndDateTime = CurrentBarDateTime.GetDate(); StartDateTime.SetTime(Input_StartTime.GetTime()); EndDateTime.SetTime(Input_EndTime.GetTime()); bool TimesAreReversed = false; if (Input_StartTime.GetTime() > Input_EndTime.GetTime()) { TimesAreReversed = true; if (CurrentBarDateTime.GetTimeInSeconds() < Input_StartTime.GetTime()) { StartDateTime -= DAYS; } else { EndDateTime += DAYS; } } if(TimesAreReversed && Input_FridayEveningExtendsIntoSunday.GetYesNo()) { SCDateTime TradingDayDate(sc.GetTradingDayDate(CurrentBarDateTime)); int DayOfWeek = TradingDayDate.GetDayOfWeek(); if (DayOfWeek == MONDAY) { StartDateTime -= 2 * DAYS; NeedReset = false; } } //reset if (NeedReset) { HighOfPeriod = -FLT_MAX; LowOfPeriod = FLT_MAX; } bool OutsideTimeRange = true; if (CurrentBarDateTime >= StartDateTime && CurrentBarDateTime <= EndDateTime) { OutsideTimeRange = false; if (HighOfPeriod < sc.BaseData[Input_InputDataHigh.GetInputDataIndex()][Index]) HighOfPeriod = sc.BaseData[Input_InputDataHigh.GetInputDataIndex()][Index]; if (LowOfPeriod > sc.BaseData[Input_InputDataLow.GetInputDataIndex()][Index]) LowOfPeriod = sc.BaseData[Input_InputDataLow.GetInputDataIndex()][Index]; } if (HighOfPeriod == -FLT_MAX) continue; // Set/update all values for current day int BackIndex = Index; while (true) { if(BackIndex < 0) break; const SCDateTime BackIndexDateTime = sc.BaseDateTimeIn[BackIndex]; if (!OutsideTimeRange && BackIndexDateTime < StartDateTime) break; HighOfDay[BackIndex] = HighOfPeriod; LowOfDay[BackIndex] = LowOfPeriod; if (OutsideTimeRange || Input_DisplayHighLowIncrementally.GetYesNo()) break; BackIndex--; if(sc.UpdateStartIndex != 0 && BackIndex >= 0) sc.EarliestUpdateSubgraphDataArrayIndex = BackIndex; } } } /*============================================================================*/ SCSFExport scsf_HighLowForTimePeriod(SCStudyInterfaceRef sc) { SCSubgraphRef HighOfDay = sc.Subgraph[0]; SCSubgraphRef LowOfDay = sc.Subgraph[1]; SCFloatArrayRef TimeRangeHigh = sc.Subgraph[0].Arrays[0]; SCFloatArrayRef TimeRangeLow = sc.Subgraph[0].Arrays[1]; SCInputRef StartTime = sc.Input[0]; SCInputRef EndTime = sc.Input[1]; SCInputRef Version = sc.Input[2]; SCInputRef InputDataHigh = sc.Input[3]; SCInputRef InputDataLow = sc.Input[4]; SCInputRef DisplayHighLowIncrementally = sc.Input[5]; SCInputRef NumberDaysToCalculate = sc.Input[6]; if (sc.SetDefaults) { sc.GraphName = "High/Low for Time Period"; sc.GraphRegion = 0; sc.AutoLoop = 0; HighOfDay.Name = "High"; HighOfDay.DrawStyle = DRAWSTYLE_STAIR_STEP; HighOfDay.PrimaryColor = RGB(0,255,0); HighOfDay.DrawZeros = false; LowOfDay.Name = "Low"; LowOfDay.DrawStyle = DRAWSTYLE_STAIR_STEP; LowOfDay.PrimaryColor = RGB(255,0,255); LowOfDay.DrawZeros = false; StartTime.Name = "Start Time"; StartTime.SetTime(0); EndTime.Name = "End Time"; EndTime.SetTime(SECONDS_PER_DAY - 1); InputDataHigh.Name = "Input Data High"; InputDataHigh.SetInputDataIndex(SC_HIGH); InputDataLow.Name = "Input Data Low"; InputDataLow.SetInputDataIndex(SC_LOW); DisplayHighLowIncrementally.Name = "Display High Low Incrementally"; DisplayHighLowIncrementally.SetYesNo(false); NumberDaysToCalculate.Name= "Number Of Days To Calculate"; NumberDaysToCalculate.SetInt(10000); Version.SetInt(2); return; } if(Version.GetInt() < 2 ) { InputDataHigh.SetInputDataIndex(SC_HIGH); InputDataLow.SetInputDataIndex(SC_LOW); Version.SetInt(2); } if (NumberDaysToCalculate.GetInt() <= 0) NumberDaysToCalculate.SetInt(10000); int InputDataHighIndex = InputDataHigh.GetInputDataIndex(); int InputDataLowIndex = InputDataLow.GetInputDataIndex(); SCDateTime InStartTime = StartTime.GetDateTime(); SCDateTime InEndTime = EndTime.GetDateTime(); for(int Index = sc.UpdateStartIndex; Index < sc.ArraySize; Index++) { SCDateTime DaysToCalculateStartDateTime = sc.GetTradingDayStartDateTimeOfBar(sc.BaseDateTimeIn[sc.ArraySize-1]) - ( NumberDaysToCalculate.GetInt() - 1 ); if (sc.BaseDateTimeIn[Index] < DaysToCalculateStartDateTime) continue; SCDateTime StartDateTime = 0; SCDateTime EndDateTime = 0; SCDateTime BarDate = sc.BaseDateTimeIn[Index].GetDate(); if(InStartTime < InEndTime) { StartDateTime = BarDate + InStartTime; EndDateTime = BarDate + InEndTime; } //Times are reversed and the current time is greater than or equal to the start time else if (sc.BaseDateTimeIn[Index].GetTimeInSeconds() >= InStartTime.GetTimeInSeconds() ) { StartDateTime = BarDate + InStartTime; EndDateTime = BarDate + 1 + InEndTime; } //Times are reversed and the current time is less than or equal to the end time else if (sc.BaseDateTimeIn[Index].GetTimeInSeconds() <= InEndTime.GetTimeInSeconds() ) { StartDateTime = BarDate + InStartTime - 1; EndDateTime = BarDate + InEndTime; } //Initial calculations or start of new time range if(Index == 0 || sc.BaseDateTimeIn[Index - 1] < StartDateTime) { TimeRangeHigh[Index] = -FLT_MAX; TimeRangeLow[Index] = FLT_MAX; } else { TimeRangeHigh[Index] = TimeRangeHigh[Index - 1]; TimeRangeLow[Index] = TimeRangeLow[Index - 1]; } //Outside of range if(sc.BaseDateTimeIn[Index] > EndDateTime || sc.BaseDateTimeIn[Index] < StartDateTime) continue; if(sc.BaseData[InputDataHighIndex].GetArraySize() > 0) { if(TimeRangeHigh[Index] < sc.BaseData[InputDataHighIndex][Index]) TimeRangeHigh[Index] = sc.BaseData[InputDataHighIndex][Index]; } else { if(TimeRangeHigh[Index] < sc.BaseData[0][Index]) TimeRangeHigh[Index] = sc.BaseData[0][Index]; } if(sc.BaseData[InputDataLowIndex].GetArraySize() > 0) { if(TimeRangeLow[Index] > sc.BaseData[InputDataLowIndex][Index]) TimeRangeLow[Index] = sc.BaseData[InputDataLowIndex][Index]; } else { if(TimeRangeLow[Index] < sc.BaseData[0][Index]) TimeRangeLow[Index] = sc.BaseData[0][Index]; } if (DisplayHighLowIncrementally.GetYesNo()) { HighOfDay[Index] = TimeRangeHigh[Index]; LowOfDay[Index] = TimeRangeLow[Index]; } else { int BackIndex = Index; while(true) { if(BackIndex < 0) break; SCDateTime IndexDateTime = sc.BaseDateTimeIn[BackIndex]; if(IndexDateTime < StartDateTime) break; HighOfDay[BackIndex] = TimeRangeHigh[Index]; LowOfDay[BackIndex] = TimeRangeLow[Index]; BackIndex--; if(sc.UpdateStartIndex != 0) sc.EarliestUpdateSubgraphDataArrayIndex = BackIndex; } } } } /*============================================================================*/ SCSFExport scsf_WriteBarDataToFile(SCStudyInterfaceRef sc) { SCInputRef Separator = sc.Input[0]; SCInputRef UseGMTTime = sc.Input[1]; SCInputRef DateFormat = sc.Input[2]; SCInputRef OutputMilliseconds = sc.Input[3]; if(sc.SetDefaults) { sc.GraphName="Write Bar Data To File"; sc.StudyDescription="Write Bar Data To File"; sc.GraphRegion = 0; Separator.Name = "Separator"; Separator.SetCustomInputStrings("Space;Comma;Tab"); Separator.SetCustomInputIndex(1); UseGMTTime.Name = "Use GMT Time"; UseGMTTime.SetYesNo(0); DateFormat.Name = "Date Format"; DateFormat.SetCustomInputStrings("MM/DD/YYYY;YYYY/MM/DD;DD/MM/YYYY"); DateFormat.SetCustomInputIndex(1); OutputMilliseconds.Name="Output Milliseconds"; OutputMilliseconds. SetYesNo(false); sc.TextInputName = "File Path"; sc.AutoLoop= 0;//manual looping for efficiency return; } SCString OutputPathAndFileName; if(sc.TextInput.GetLength() > 0) { OutputPathAndFileName = sc.TextInput; } else { OutputPathAndFileName.Format("%s-BarData.txt", sc.Symbol.GetChars()); } HANDLE FileHandle = INVALID_HANDLE_VALUE; DWORD BytesWritten; if(sc.UpdateStartIndex == 0) { // create new file FileHandle = CreateFileA(OutputPathAndFileName.GetChars(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL, NULL); // creating/opening fail if(FileHandle == INVALID_HANDLE_VALUE) { SCString LogMessage; LogMessage.Format("Write Bar Data To File study: Error creating output data file: %s. Make sure the path is valid and there are no invalid characters.", OutputPathAndFileName.GetChars()); sc.AddMessageToLog(LogMessage.GetChars(), 1); return; } // write file header SCString FileHeader; switch(Separator.GetInt()) { case 0: FileHeader = "Date Time Open High Low Close Volume NumberOfTrades BidVolume AskVolume\r\n"; break; case 1: FileHeader = "Date, Time, Open, High, Low, Close, Volume, NumberOfTrades, BidVolume, AskVolume\r\n"; break; case 2: FileHeader = "Date\tTime\tOpen\tHigh\tLow\tClose\tVolume\tNumberOfTrades\tBidVolume\tAskVolume\r\n"; break; } WriteFile(FileHandle, FileHeader.GetChars(), (DWORD)FileHeader.GetLength(), &BytesWritten, NULL); } else { // open existing file FileHandle = CreateFileA(OutputPathAndFileName.GetChars(),GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); // creating/opening fail if(FileHandle == INVALID_HANDLE_VALUE) { SCString LogMessage; LogMessage.Format("Write Bar Data To File study: Error creating output data file: %s", OutputPathAndFileName.GetChars()); sc.AddMessageToLog(LogMessage.GetChars(), 1); return; } SetFilePointer(FileHandle, 0, NULL, FILE_END); } bool IsRenko = sc.AreRenkoBars() != 0; for (int Index=sc.UpdateStartIndex;Index<(sc.ArraySize-1);Index++) { if (sc.GetBarHasClosedStatus(Index) != BHCS_BAR_HAS_CLOSED) continue; // write on close int Year,Month, Day; int hour, minute, second, millisecond; SCDateTimeMS BaseDateTimeIn = sc.BaseDateTimeIn[Index]; if (UseGMTTime.GetBoolean() != 0) BaseDateTimeIn = sc.AdjustDateTimeToGMT(BaseDateTimeIn); BaseDateTimeIn.GetDateTimeYMDHMS_MS( Year, Month, Day, hour, minute, second, millisecond); SCString DateString; switch (DateFormat.GetInt()) { case 0: DateString.Format("%02d/%02d/%d", Month, Day, Year); break; case 1: DateString.Format("%d/%02d/%02d", Year, Month, Day); break; case 2: DateString.Format("%02d/%02d/%d", Day, Month, Year); break; } // write bar data string to file int ValueFormat = sc.BaseGraphValueFormat; char MillisecondsText[32] ={0}; if(OutputMilliseconds.GetYesNo()) sprintf_s(MillisecondsText, ".%d", millisecond); const char *FormatString ; switch(Separator.GetInt()) { case 0: FormatString = "%s %.2d:%.2d:%.2d%s %s %s %s %s %.0f %.0f %.0f %.0f\r\n"; break; case 1: FormatString = "%s, %.2d:%.2d:%.2d%s, %s, %s, %s, %s, %.0f, %.0f, %.0f, %.0f\r\n"; break; default: case 2: FormatString = "%s\t%.2d:%.2d:%.2d%s\t%s\t%s\t%s\t%s\t%.0f\t%.0f\t%.0f\t%.0f\r\n"; break; } float OpenValue = IsRenko ? sc.BaseData[SC_RENKO_OPEN][Index] : sc.Open[Index]; float HighValue = sc.High[Index]; float LowValue = sc.Low[Index]; float CloseValue = IsRenko ? sc.BaseData[SC_RENKO_CLOSE][Index] : sc.Close[Index]; SCString BarDataString; BarDataString.Format(FormatString, DateString.GetChars(), hour, minute, second, MillisecondsText, sc.FormatGraphValue(OpenValue, ValueFormat).GetChars(), sc.FormatGraphValue(HighValue, ValueFormat).GetChars(), sc.FormatGraphValue(LowValue, ValueFormat).GetChars(), sc.FormatGraphValue(CloseValue, ValueFormat).GetChars(), sc.Volume[Index], sc.NumberOfTrades[Index], sc.BidVolume[Index], sc.AskVolume[Index]); WriteFile(FileHandle,BarDataString.GetChars(),(DWORD)BarDataString.GetLength(),&BytesWritten,NULL); } CloseHandle(FileHandle); return; } /*============================================================================*/ SCSFExport scsf_WriteBarAndStudyDataToFile(SCStudyInterfaceRef sc) { SCInputRef Input_IncludeHiddenStudies = sc.Input[0]; SCInputRef Input_UseGMTTime = sc.Input[1]; SCInputRef Input_IncludeHiddenSubgraphs = sc.Input[2]; SCInputRef Input_OutputMilliseconds = sc.Input[3]; if(sc.SetDefaults) { sc.GraphName="Write Bar and Study Data To File"; sc.GraphRegion = 0; Input_IncludeHiddenStudies.Name = "Include Hidden Studies"; Input_IncludeHiddenStudies.SetYesNo(true); //Input_UseGMTTime.Name = "Use GMT Time"; //Input_UseGMTTime.SetYesNo(0); Input_IncludeHiddenSubgraphs.Name = "Include Hidden Subgraphs"; Input_IncludeHiddenSubgraphs.SetYesNo(false); //Input_OutputMilliseconds.Name = "Output Milliseconds"; //Input_OutputMilliseconds.SetYesNo(false); sc.TextInputName = "Path and File Name"; sc.CalculationPrecedence = VERY_LOW_PREC_LEVEL; sc.AutoLoop = 0; //manual looping required return; } if (sc.LastCallToFunction) return; SCString OutputPathAndFileName; if(!sc.TextInput.IsEmpty()) { OutputPathAndFileName = sc.TextInput; } else { OutputPathAndFileName.Format("%s-BarStudyData.csv", sc.Symbol.GetChars()); } //sc.WriteBarAndStudyDataToFile(sc.UpdateStartIndex, OutputPathAndFileName, IncludeHiddenStudies.GetYesNo(), IncludeHiddenSubgraphs.GetYesNo()); n_ACSIL::s_WriteBarAndStudyDataToFile WriteBarAndStudyDataToFileParams; WriteBarAndStudyDataToFileParams.StartingIndex = sc.UpdateStartIndex; WriteBarAndStudyDataToFileParams.OutputPathAndFileName = OutputPathAndFileName; WriteBarAndStudyDataToFileParams.IncludeHiddenStudies = Input_IncludeHiddenStudies.GetYesNo(); WriteBarAndStudyDataToFileParams.IncludeHiddenSubgraphs = Input_IncludeHiddenSubgraphs.GetYesNo(); WriteBarAndStudyDataToFileParams.AppendOnlyToFile = 0; WriteBarAndStudyDataToFileParams.IncludeLastBar = 0; sc.WriteBarAndStudyDataToFileEx(WriteBarAndStudyDataToFileParams); return; } /*============================================================================*/ bool IsFractalBuySignal(SCFloatArrayRef InDataLow, SCFloatArrayRef InDataHigh, int Index); //Long Fractal bool IsFractalSellSignal(SCFloatArrayRef InDataLow, int Index); //Short Fractal SCSFExport scsf_FractalSignals(SCStudyInterfaceRef sc) { enum SubgraphIndexes { INDEX_SIGNAL_BUY = 0, INDEX_SIGNAL_SELL }; SCSubgraphRef Buy = sc.Subgraph[0]; SCSubgraphRef Sell = sc.Subgraph[1]; SCInputRef SubgraphOffset = sc.Input[0]; SCInputRef Version = sc.Input[6]; if(sc.SetDefaults) { sc.GraphName="Bill Williams Fractals"; sc.AutoLoop = 1; sc.GraphRegion = 0; Buy.Name = "Buy"; Buy.DrawStyle = DRAWSTYLE_TRIANGLE_UP; Buy.PrimaryColor = RGB(0, 255, 0); Buy.LineWidth = 5; Buy.DrawZeros = false; Sell.Name = "Sell"; Sell.DrawStyle = DRAWSTYLE_TRIANGLE_DOWN; Sell.PrimaryColor = RGB(255, 0, 0); Sell.LineWidth = 5; Sell.DrawZeros = false; Version.SetInt(2); SubgraphOffset.Name = "Arrow Offset Percentage"; SubgraphOffset.SetFloat(2.0f); sc.AutoLoop = 0; return; } int CalculationStartIndex = max(0, sc.UpdateStartIndex - 4); sc.EarliestUpdateSubgraphDataArrayIndex = CalculationStartIndex; for (int Index = CalculationStartIndex; Index < sc.ArraySize; Index++) { float Range = sc.High[Index] - sc.Low[Index]; float Offset = Range * (SubgraphOffset.GetFloat()*0.01f); // detect buy fractal signal if(IsFractalBuySignal(sc.Low, sc.High, Index)) Buy[Index] = sc.High[Index] + Offset; else Buy[Index] = 0; // detect sell fractal signal if(IsFractalSellSignal(sc.Low, Index)) Sell[Index] = sc.Low[Index] - Offset; else Sell[Index] = 0; } } /*============================================================================*/ bool IsFractalBuySignal(SCFloatArrayRef InDataLow, SCFloatArrayRef InDataHigh, int Index) { int ArraySize = InDataLow.GetArraySize(); if ( ( Index + 2 < ArraySize && Index - 2 >= 0 && InDataHigh[Index] > InDataHigh[Index + 1] && InDataHigh[Index + 1] > InDataHigh[Index + 2] && InDataHigh[Index] > InDataHigh[Index - 1] && InDataHigh[Index - 1] > InDataHigh[Index - 2] && InDataLow[Index] >= InDataLow[Index + 1] && InDataLow[Index] >= InDataLow[Index - 1] && InDataLow[Index - 1] > InDataLow[Index - 2] ) || ( Index + 3 < ArraySize && Index - 2 >= 0 && InDataHigh[Index] > InDataHigh[Index + 2] && InDataHigh[Index] > InDataHigh[Index + 3] && InDataHigh[Index] > InDataHigh[Index - 1] && InDataHigh[Index] > InDataHigh[Index - 2] && InDataHigh[Index] == InDataHigh[Index + 1] ) || ( Index + 4 < ArraySize && Index - 2 >= 0 && InDataHigh[Index] > InDataHigh[Index + 3] && InDataHigh[Index] > InDataHigh[Index + 4] && InDataHigh[Index] > InDataHigh[Index - 1] && InDataHigh[Index] > InDataHigh[Index - 2] && InDataHigh[Index] == InDataHigh[Index + 1] && InDataHigh[Index + 1] == InDataHigh[Index + 2] ) ) return true; return false; } /*============================================================================*/ bool IsFractalSellSignal(SCFloatArrayRef InDataLow, int Index) { int ArraySize = InDataLow.GetArraySize(); if ( ( Index + 2 < ArraySize && Index - 2 >= 0 && InDataLow[Index] < InDataLow[Index + 1] && InDataLow[Index + 1] < InDataLow[Index + 2] && InDataLow[Index] < InDataLow[Index - 1] && InDataLow[Index] < InDataLow[Index - 2] ) || ( Index + 3 < ArraySize && Index - 2 >= 0 && InDataLow[Index] < InDataLow[Index + 2] && InDataLow[Index] < InDataLow[Index + 3] && InDataLow[Index] < InDataLow[Index - 1] && InDataLow[Index] < InDataLow[Index - 2] && InDataLow[Index] == InDataLow[Index + 1] ) || ( Index + 4 < ArraySize && Index - 2 >= 0 && InDataLow[Index] < InDataLow[Index + 3] && InDataLow[Index] < InDataLow[Index + 4] && InDataLow[Index] < InDataLow[Index - 1] && InDataLow[Index] < InDataLow[Index - 2] && InDataLow[Index] == InDataLow[Index + 1] && InDataLow[Index + 1] == InDataLow[Index + 2] ) ) return true; return false; } /*============================================================================*/ SCSFExport scsf_RoundTick(SCStudyInterfaceRef sc) { SCSubgraphRef Value = sc.Subgraph[0]; SCInputRef InputData = sc.Input[0]; if(sc.SetDefaults) { sc.GraphName="Round Study Subgraph to Tick Size"; sc.StudyDescription="Rounds the elements in the array from the Base Data selected by the Input Data option, to the nearest value based upon the Tick Size setting in the chart"; Value.Name = "Value"; Value.DrawStyle = DRAWSTYLE_LINE; Value.PrimaryColor = RGB(0, 0, 255); Value.LineWidth = 2; Value.DrawZeros = false; InputData.Name = "Input Data"; InputData.SetInputDataIndex(SC_OPEN); sc.AutoLoop = 1; return; } Value[sc.Index] = (float)sc.RoundToTickSize(sc.BaseDataIn[ InputData.GetInputDataIndex()][sc.Index], sc.TickSize); } /*============================================================================*/ SCSFExport scsf_MACDVolumeWeighted(SCStudyInterfaceRef sc) { SCSubgraphRef Macd = sc.Subgraph[0]; SCSubgraphRef MaMacd = sc.Subgraph[1]; SCSubgraphRef MacdDiff = sc.Subgraph[2]; SCSubgraphRef RefLine = sc.Subgraph[3]; SCInputRef FastLen = sc.Input[0]; SCInputRef SlowLen = sc.Input[1]; SCInputRef MacdLen = sc.Input[2]; SCInputRef InputData = sc.Input[3]; if(sc.SetDefaults) { sc.GraphName="MACD-Volume Weighted"; sc.AutoLoop = 1; sc.GraphRegion = 1; sc.ValueFormat = 3; Macd.Name = "MACD"; Macd.DrawStyle = DRAWSTYLE_LINE; Macd.PrimaryColor = RGB(0,255,0); Macd.DrawZeros = true; MaMacd.Name = "MA of MACD"; MaMacd.DrawStyle = DRAWSTYLE_LINE; MaMacd.PrimaryColor = RGB(255,0,255); MaMacd.DrawZeros = true; MacdDiff.Name = "MACD Diff"; MacdDiff.DrawStyle = DRAWSTYLE_BAR; MacdDiff.PrimaryColor = RGB(255,255,0); MacdDiff.DrawZeros = true; RefLine.Name = "Line"; RefLine.DrawStyle = DRAWSTYLE_LINE; RefLine.PrimaryColor = RGB(255,127,0); RefLine.DrawZeros = true; FastLen.Name ="Fast Moving Average Length"; FastLen.SetInt(12); FastLen.SetIntLimits(1,MAX_STUDY_LENGTH); SlowLen.Name = "Slow Moving Average Length"; SlowLen.SetInt(26); SlowLen.SetIntLimits(1,MAX_STUDY_LENGTH); MacdLen.Name = "MACD Moving Average Length"; MacdLen.SetInt(9); MacdLen.SetIntLimits(1,MAX_STUDY_LENGTH); InputData.Name = "Input Data"; InputData.SetInputDataIndex(SC_LAST); return; } sc.DataStartIndex = MacdLen.GetInt() + max(FastLen.GetInt(), SlowLen.GetInt()); int i = sc.Index; SCFloatArrayRef FastOut = Macd.Arrays[0]; sc.VolumeWeightedMovingAverage(sc.BaseDataIn[InputData.GetInputDataIndex()], sc.Volume, FastOut, FastLen.GetInt()); SCFloatArrayRef SlowOut = Macd.Arrays[1]; sc.VolumeWeightedMovingAverage(sc.BaseDataIn[InputData.GetInputDataIndex()], sc.Volume, SlowOut, SlowLen.GetInt()); Macd[i] = FastOut[i] - SlowOut[i]; if(i < max(SlowLen.GetInt(), FastLen.GetInt()) + MacdLen.GetInt()) return; sc.MovingAverage(Macd, MaMacd, MOVAVGTYPE_EXPONENTIAL, MacdLen.GetInt()); MacdDiff[i] = Macd[i] - MaMacd[i]; RefLine[i] = 0; } /*============================================================================*/ SCSFExport scsf_StandardDeviation(SCStudyInterfaceRef sc) { SCSubgraphRef Deviation = sc.Subgraph[0]; SCInputRef InputData = sc.Input[0]; SCInputRef Length = sc.Input[1]; if(sc.SetDefaults) { sc.GraphName = "Standard Deviation"; sc.AutoLoop = 1; Deviation.Name = "Deviation"; Deviation.DrawStyle = DRAWSTYLE_LINE; Deviation.PrimaryColor = RGB(0,255,0); Deviation.DrawZeros = true; InputData.Name = "Input Data"; InputData.SetInputDataIndex(SC_LAST); Length.Name ="Length"; Length.SetInt(14); Length.SetIntLimits(1,MAX_STUDY_LENGTH); return; } sc.DataStartIndex = Length.GetInt(); sc.StdDeviation(sc.BaseDataIn[InputData.GetInputDataIndex()], Deviation, Length.GetInt()); } /*============================================================================*/ SCSFExport scsf_AutoRetracementProjection(SCStudyInterfaceRef sc) { SCSubgraphRef PeriodHigh = sc.Subgraph[0]; SCSubgraphRef PeriodLow = sc.Subgraph[1]; const int SubgraphLevelsStartIndex = 2; const int NumberOfLevels = 14; SCInputRef TimePeriodType = sc.Input[0]; SCInputRef TimePeriodLength = sc.Input[1]; SCInputRef PlotType = sc.Input[2]; SCInputRef Version = sc.Input[17]; SCInputRef NewPeriodDaySessionStart = sc.Input[18]; SCInputRef CalculationReferenceValue =sc.Input[19]; SCInputRef RoundToTickSize = sc.Input[20]; SCInputRef ReferenceSingleSubgraph = sc.Input[21]; SCInputRef NumberOfDaysToCalculate = sc.Input[22]; if(sc.SetDefaults) { sc.GraphName = "Auto Retracement/Projection"; sc.GraphRegion = 0; sc.AutoLoop = 0;//Manual looping PeriodHigh.Name = "Period High"; PeriodHigh.DrawStyle = DRAWSTYLE_LINE; PeriodHigh.PrimaryColor = RGB(255, 165, 0); PeriodHigh.LineWidth = 2; PeriodHigh.DrawZeros = false; PeriodLow.Name = "Period Low"; PeriodLow.DrawStyle = DRAWSTYLE_LINE; PeriodLow.PrimaryColor = RGB(255, 165, 0); PeriodLow.LineWidth = 2; PeriodLow.DrawZeros = false; for (int LevelIndex = 0; LevelIndex < NumberOfLevels; LevelIndex++) { SCString TmpStr; TmpStr.Format("Level%d", LevelIndex + 1); sc.Subgraph[LevelIndex + SubgraphLevelsStartIndex].Name = TmpStr; sc.Subgraph[LevelIndex + SubgraphLevelsStartIndex].DrawStyle = DRAWSTYLE_DASH; sc.Subgraph[LevelIndex + SubgraphLevelsStartIndex].LineStyle = LINESTYLE_SOLID; sc.Subgraph[LevelIndex + SubgraphLevelsStartIndex].LineWidth = 2; sc.Subgraph[LevelIndex + SubgraphLevelsStartIndex].PrimaryColor = RGB(0, 255, 255); sc.Subgraph[LevelIndex + SubgraphLevelsStartIndex].DrawZeros = false; TmpStr.Format("Level %d Percentage .01 = 1%%", LevelIndex + 1); sc.Input[3 + LevelIndex].Name = TmpStr; } PlotType.Name = "Calculation Method"; PlotType.SetCustomInputStrings("Projection;Retracement"); PlotType.SetCustomInputIndex( 1); sc.Input[3].SetFloat(0.236f); sc.Input[4].SetFloat(0.382f); sc.Input[5].SetFloat(0.50f); sc.Input[6].SetFloat(0.618f); for (int LevelIndex = 7; LevelIndex < NumberOfLevels + 3; LevelIndex++) sc.Input[LevelIndex].SetFloat(0.0f); TimePeriodType.Name = "Time Period Unit"; TimePeriodType.SetTimePeriodType(TIME_PERIOD_LENGTH_UNIT_DAYS); TimePeriodLength.Name = "Time Period Unit Length"; TimePeriodLength.SetInt(1); Version.SetInt(2); NewPeriodDaySessionStart .Name ="New Period at Day Session Start when Using Evening Session"; NewPeriodDaySessionStart.SetYesNo(false); CalculationReferenceValue.Name = "Calculation Reference Value"; CalculationReferenceValue.SetCustomInputStrings("Automatic;Use High;Use Low"); CalculationReferenceValue.SetCustomInputIndex(1); RoundToTickSize.Name = "Round To Nearest Tick Size"; RoundToTickSize.SetYesNo(0); ReferenceSingleSubgraph.Name = "Reference Single Subgraph"; ReferenceSingleSubgraph.SetYesNo(false); NumberOfDaysToCalculate.Name = "Number of Days to Calculate"; NumberOfDaysToCalculate.SetInt(120); NumberOfDaysToCalculate.SetIntLimits(1, MAX_STUDY_LENGTH); return; } if (Version.GetInt() < 1) { TimePeriodType.SetTimePeriodType(TIME_PERIOD_LENGTH_UNIT_DAYS); TimePeriodLength.SetInt(1); Version.SetInt(1); } if (Version.GetInt() < 2) { NumberOfDaysToCalculate.SetInt(1000); Version.SetInt(2); } float& OpenOfDay = sc.GetPersistentFloat(1); int TimePeriodTypeInput = TimePeriodType.GetTimePeriodType(); int TimePeriodLengthInput = TimePeriodLength.GetInt(); float LevelsPercentages[NumberOfLevels]; for (int Index = 0; Index < NumberOfLevels; Index++) { LevelsPercentages[Index] = sc.Input[Index + 3].GetFloat(); } int OpenSubgraph = SC_OPEN; int HighSubgraph = SC_HIGH; int LowSubgraph = SC_LOW; int LastSubgraph = SC_LAST; if (ReferenceSingleSubgraph.GetYesNo()) { OpenSubgraph = SC_OPEN; HighSubgraph = SC_OPEN; LowSubgraph = SC_OPEN; LastSubgraph = SC_OPEN; } // Main loop for (int Index = sc.UpdateStartIndex; Index < sc.ArraySize; Index++) { SCDateTime TradingDayDateForBar = sc.GetTradingDayDate(sc.BaseDateTimeIn[Index]); SCDateTime TradingDayDateForLastBar = sc.GetTradingDayDate(sc.BaseDateTimeIn[sc.ArraySize - 1]); if ((TradingDayDateForLastBar.GetDate() - TradingDayDateForBar.GetDate() + 1) > NumberOfDaysToCalculate.GetInt()) { continue; } SCDateTime PriorCurrentPeriodStartDateTime = sc.GetStartOfPeriodForDateTime(sc.BaseDateTimeIn[Index - 1], TimePeriodTypeInput, TimePeriodLengthInput, 0, NewPeriodDaySessionStart.GetYesNo()); SCDateTime CurrentPeriodStartDateTime = sc.GetStartOfPeriodForDateTime(sc.BaseDateTimeIn[Index], TimePeriodTypeInput, TimePeriodLengthInput, 0, NewPeriodDaySessionStart.GetYesNo()); bool IsInNewPeriod = PriorCurrentPeriodStartDateTime != CurrentPeriodStartDateTime ; if (IsInNewPeriod) //reset values { OpenOfDay = sc.BaseData[OpenSubgraph][Index]; PeriodHigh[Index] = sc.BaseData[HighSubgraph][Index]; PeriodLow[Index] = sc.BaseData[LowSubgraph][Index]; } else { if (sc.BaseData[HighSubgraph][Index] > PeriodHigh[Index - 1] || Index == 0) PeriodHigh[Index] = sc.BaseData[HighSubgraph][Index]; else PeriodHigh[Index] = PeriodHigh[Index - 1]; if (sc.BaseData[LowSubgraph][Index] < PeriodLow[Index - 1] || Index == 0) PeriodLow[Index] = sc.BaseData[LowSubgraph][Index]; else PeriodLow[Index] = PeriodLow[Index - 1]; } float Range = PeriodHigh[Index] - PeriodLow[Index]; for (int LevelIndex = 0; LevelIndex < NumberOfLevels; LevelIndex++) { if (LevelsPercentages[LevelIndex] == 0) continue; float Value = 0; if (PlotType.GetInt() == 1)//Retracement { //rising prices if ((CalculationReferenceValue.GetIndex() == 0 && sc.BaseData[LastSubgraph][Index] >= OpenOfDay) ||CalculationReferenceValue.GetIndex() == 1) Value = PeriodHigh[Index] - LevelsPercentages[LevelIndex] * Range; else Value = LevelsPercentages[LevelIndex] * Range + PeriodLow[Index]; } else//Projection { if ((CalculationReferenceValue.GetIndex()== 0 && sc.BaseData[LastSubgraph][Index] >= OpenOfDay) ||CalculationReferenceValue.GetIndex()== 1) Value = LevelsPercentages[LevelIndex] * Range + PeriodHigh[Index]; else Value = PeriodLow[Index] - LevelsPercentages[LevelIndex] * Range; } if (RoundToTickSize.GetYesNo()) Value = (float)sc.RoundToTickSize(Value, sc.TickSize); sc.Subgraph[SubgraphLevelsStartIndex + LevelIndex][Index] = Value; } } } /*============================================================================*/ SCSFExport scsf_NewHighLowAlert(SCStudyInterfaceRef sc) { SCInputRef HighAlert = sc.Input[0]; SCInputRef LowAlert = sc.Input[1]; if(sc.SetDefaults) { sc.GraphName = "New Daily High/Low Alert"; sc.AutoLoop = 0; sc.GraphRegion = 0; HighAlert.Name = "High Alert Sound"; HighAlert.SetAlertSoundNumber(2); LowAlert.Name = "Low Alert Sound"; LowAlert.SetAlertSoundNumber(2); return; } float & PreviousHigh = sc.GetPersistentFloat(1); float & PreviousLow = sc.GetPersistentFloat(2); SCDateTime TradingDayDate = sc.GetTradingDayDate(sc.BaseDateTimeIn[sc.ArraySize - 1]); float DailyOpen; float DailyHigh; float DailyLow; float DailyClose; if(!sc.GetOHLCForDate(TradingDayDate, DailyOpen, DailyHigh, DailyLow, DailyClose)) return; if(sc.UpdateStartIndex == 0) { PreviousHigh = DailyHigh; PreviousLow = DailyLow; return; } SCString Message; if(HighAlert.GetAlertSoundNumber() > 0 && PreviousHigh != 0.0 && DailyHigh > PreviousHigh) { Message.Format("New Daily High: %f. Previous high: %f", DailyHigh, PreviousHigh); sc.PlaySound(HighAlert.GetAlertSoundNumber() - 1, Message); } if(LowAlert.GetAlertSoundNumber() > 0 && PreviousLow != 0.0 && DailyLow < PreviousLow) { Message.Format("New Daily Low: %f. Previous low: %f", DailyLow, PreviousLow); sc.PlaySound(LowAlert.GetAlertSoundNumber() - 1 , Message); } PreviousHigh = DailyHigh; PreviousLow = DailyLow; } /*============================================================================*/ SCSFExport scsf_Spread4Chart(SCStudyInterfaceRef sc) { SCSubgraphRef Open = sc.Subgraph[0]; SCSubgraphRef High = sc.Subgraph[1]; SCSubgraphRef Low = sc.Subgraph[2]; SCSubgraphRef Last = sc.Subgraph[3]; SCSubgraphRef Volume = sc.Subgraph[4]; SCSubgraphRef OpenInterest = sc.Subgraph[5]; SCSubgraphRef OHLCAvg = sc.Subgraph[6]; SCSubgraphRef HLCAvg = sc.Subgraph[7]; SCSubgraphRef HLAvg = sc.Subgraph[8]; SCInputRef Chart2Number = sc.Input[0]; SCInputRef Chart3Number = sc.Input[1]; SCInputRef Chart4Number = sc.Input[2]; SCInputRef Chart1Multiplier = sc.Input[3]; SCInputRef Chart2Multiplier = sc.Input[4]; SCInputRef Chart3Multiplier = sc.Input[5]; SCInputRef Chart4Multiplier = sc.Input[6]; if (sc.SetDefaults) { sc.GraphName = "Spread - 4 Chart"; sc.GraphRegion = 1; sc.UseGlobalChartColors = 1; sc.GraphDrawType = GDT_OHLCBAR; sc.StandardChartHeader = 1; // We are using Manual looping. sc.AutoLoop = false; Open.Name = "Open"; Open.DrawStyle = DRAWSTYLE_LINE; Open.PrimaryColor = RGB(0,255,0); Open.DrawZeros = false; High.Name = "High"; High.DrawStyle = DRAWSTYLE_LINE; High.PrimaryColor = RGB(0,255,0); High.DrawZeros = false; Low.Name = "Low"; Low.DrawStyle = DRAWSTYLE_LINE; Low.PrimaryColor = RGB(0,255,0); Low.DrawZeros = false; Last.Name = "Last"; Last.DrawStyle = DRAWSTYLE_LINE; Last.PrimaryColor = RGB(0,255,0); Last.DrawZeros = false; Volume.Name = "Volume"; Volume.DrawStyle = DRAWSTYLE_IGNORE; Volume.PrimaryColor = RGB(255,0,0); Volume.DrawZeros = false; OpenInterest.Name = "# of Trades / OI"; OpenInterest.DrawStyle = DRAWSTYLE_IGNORE; OpenInterest.PrimaryColor = RGB(0,0,255); OpenInterest.DrawZeros = false; OHLCAvg.Name = "OHLC Avg"; OHLCAvg.DrawStyle = DRAWSTYLE_IGNORE; OHLCAvg.PrimaryColor = RGB(127,0,255); OHLCAvg.DrawZeros = false; HLCAvg.Name = "HLC Avg"; HLCAvg.DrawStyle = DRAWSTYLE_IGNORE; HLCAvg.PrimaryColor = RGB(0,255,255); HLCAvg.DrawZeros = false; HLAvg.Name = "HL Avg"; HLAvg.DrawStyle = DRAWSTYLE_IGNORE; HLAvg.PrimaryColor = RGB(0,127,255); HLAvg.DrawZeros = false; Chart2Number.Name = "Chart 2 Number"; Chart2Number.SetChartNumber(1); Chart3Number.Name = "Chart 3 Number"; Chart3Number.SetChartNumber(1); Chart4Number.Name = "Chart 4 Number"; Chart4Number.SetChartNumber(1); Chart1Multiplier.Name = "Chart 1 Multiplier"; Chart1Multiplier.SetFloat(1.0); Chart2Multiplier.Name = "Chart 2 Multiplier"; Chart2Multiplier.SetFloat(1.0); Chart3Multiplier.Name = "Chart 3 Multiplier"; Chart3Multiplier.SetFloat(1.0); Chart4Multiplier.Name = "Chart 4 Multiplier"; Chart4Multiplier.SetFloat(1.0); return; } // Obtain a reference to the Base Data in the specified chart. This call is relatively efficient, but it should be called as minimally as possible. To reduce the number of calls we have it outside of the primary "for" loop in this study function. And we also use Manual Looping by using sc.AutoLoop = 0. In this way, sc.GetChartBaseData is called only once per call to this study function and there are minimal number of calls to the function. sc.GetChartBaseData is a new function to get all of the Base Data arrays with one efficient call. SCGraphData Chart2BaseData; sc.GetChartBaseData(-Chart2Number.GetChartNumber(), Chart2BaseData); SCGraphData Chart3BaseData; sc.GetChartBaseData(-Chart3Number.GetChartNumber(), Chart3BaseData); SCGraphData Chart4BaseData; sc.GetChartBaseData(-Chart4Number.GetChartNumber(), Chart4BaseData); for (int Index = sc.UpdateStartIndex; Index < sc.ArraySize; Index++) { int Chart2Index = sc.GetNearestMatchForDateTimeIndex(Chart2Number.GetChartNumber(), Index); int Chart3Index = sc.GetNearestMatchForDateTimeIndex(Chart3Number.GetChartNumber(), Index); int Chart4Index = sc.GetNearestMatchForDateTimeIndex(Chart4Number.GetChartNumber(), Index); for (int SubgraphIndex = 0; SubgraphIndex < 6; SubgraphIndex++) { sc.Subgraph[SubgraphIndex][Index] = (sc.BaseDataIn[SubgraphIndex][Index] * Chart1Multiplier.GetFloat() - Chart2BaseData[SubgraphIndex][Chart2Index] * Chart2Multiplier.GetFloat()) - (Chart3BaseData[SubgraphIndex][Chart3Index] * Chart3Multiplier.GetFloat() - Chart4BaseData[SubgraphIndex][Chart4Index] * Chart4Multiplier.GetFloat()); } sc.Subgraph[ SC_HIGH][Index] = max(sc.Subgraph[SC_OPEN][Index], max(sc.Subgraph[SC_HIGH][Index], max(sc.Subgraph[SC_LOW][Index],sc.Subgraph[SC_LAST][Index]) ) ); sc.Subgraph[SC_LOW][Index] = min(sc.Subgraph[SC_OPEN][Index], min(sc.Subgraph[SC_HIGH][Index], min(sc.Subgraph[SC_LOW][Index],sc.Subgraph[SC_LAST][Index]) ) ); sc.CalculateOHLCAverages(Index); } //SCString Chart1Name = sc.GetStudyNameFromChart(sc.ChartNumber, 0); //SCString Chart2Name = sc.GetStudyNameFromChart(Chart2Number.GetChartNumber(), 0); //sc.GraphName.Format("Difference %s - %s", Chart1Name.GetChars(), Chart2Name.GetChars()); } /*============================================================================*/ SCSFExport scsf_QStick(SCStudyInterfaceRef sc) { SCSubgraphRef QStick = sc.Subgraph[0]; SCInputRef Length = sc.Input[0]; if (sc.SetDefaults) { // Set the configuration and defaults sc.GraphName = "Q Stick"; sc.AutoLoop = 1; QStick.Name = "QS"; QStick.DrawStyle = DRAWSTYLE_LINE; QStick.LineWidth = 2; QStick.PrimaryColor = RGB(0,255,0); Length.Name = "Length"; Length.SetInt(4); sc.GraphRegion = 1; return; } // Do data processing QStick.Arrays[0][sc.Index] = sc.BaseData[SC_LAST][sc.Index] - sc.BaseData[SC_OPEN][sc.Index] ; sc.Summation( QStick.Arrays[0], QStick.Arrays[1], Length.GetInt() ); QStick.Data[sc.Index] = QStick.Arrays[1][sc.Index] / Length.GetInt() ; } /*============================================================================*/ SCSFExport scsf_HorizontalLineAtTime(SCStudyInterfaceRef sc) { SCSubgraphRef Subgraph_HorizontalLine = sc.Subgraph[0]; SCSubgraphRef Subgraph_ExtensionLines = sc.Subgraph[1]; SCInputRef InputData = sc.Input[0]; SCInputRef StartTime = sc.Input[1]; SCInputRef UseStopTime = sc.Input[2]; SCInputRef StopTime = sc.Input[3]; SCInputRef LimitHorizontalLineFromTimeToOneDay = sc.Input[4]; SCInputRef IgnoreWeekends = sc.Input[5]; SCInputRef AddExtensionLinesUntilFutureIntersection = sc.Input[6]; SCInputRef UseAllowedRangeForMatchInMinutes = sc.Input[7]; SCInputRef AllowedRangeForMatchInMinutes = sc.Input[8]; if (sc.SetDefaults) { sc.GraphName = "Horizontal Line at Time"; sc.GraphRegion = 0; sc.AutoLoop = 1; Subgraph_HorizontalLine.Name = "Line"; Subgraph_HorizontalLine.DrawStyle = DRAWSTYLE_STAIR_STEP; Subgraph_HorizontalLine.LineWidth = 2; Subgraph_HorizontalLine.PrimaryColor = RGB(0, 255, 0); Subgraph_HorizontalLine.DrawZeros = false; Subgraph_ExtensionLines.Name = "Extension Lines"; Subgraph_ExtensionLines.DrawStyle = DRAWSTYLE_LINE; Subgraph_ExtensionLines.LineWidth = 2; Subgraph_ExtensionLines.PrimaryColor = RGB(255, 128, 0); Subgraph_ExtensionLines.DrawZeros = false; InputData.Name = "Input Data"; InputData.SetInputDataIndex(SC_LAST); StartTime.Name = "Start Time"; StartTime.SetTime(HMS_TIME(12, 00, 0)); UseStopTime.Name = "Use Stop Time"; UseStopTime.SetYesNo(false); StopTime.Name = "Stop Time"; StopTime.SetTime(HMS_TIME(23, 59, 59)); LimitHorizontalLineFromTimeToOneDay.Name = "Limit Horizontal Line From Time To 1 Day"; LimitHorizontalLineFromTimeToOneDay.SetYesNo(true); IgnoreWeekends.Name = "Ignore Weekends"; IgnoreWeekends.SetYesNo(false); AddExtensionLinesUntilFutureIntersection.Name = "Add Extension Lines Until Future Intersection"; AddExtensionLinesUntilFutureIntersection.SetYesNo(false); UseAllowedRangeForMatchInMinutes.Name = "Use Allowed Range for Match in Minutes"; UseAllowedRangeForMatchInMinutes.SetYesNo(false); AllowedRangeForMatchInMinutes.Name = "Allowed Range for Match in Minutes"; AllowedRangeForMatchInMinutes.SetInt(60); return; } float& r_PriorValue = sc.GetPersistentFloat(1); SCDateTime& r_StopDateTime = sc.GetPersistentSCDateTime(2); int & r_LastUsedBarIndexForExtensionLine = sc.GetPersistentInt(1); if (sc.Index == 0) { r_StopDateTime = 0; r_PriorValue = FLT_MIN; r_LastUsedBarIndexForExtensionLine = -1; } SCDateTime AllowedTimeRange = AllowedRangeForMatchInMinutes.GetInt() * MINUTES; SCDateTimeMS StartDateTime; StartDateTime.SetDateTimeAsDouble(sc.BaseDateTimeIn[sc.Index].GetDate() + StartTime.GetDateTime().GetTimeAsSCDateTimeMS()); SCDateTime TradingDayDate = sc.GetTradingDayDate(sc.BaseDateTimeIn[sc.Index]); bool IgnoreDate = IgnoreWeekends.GetYesNo() && TradingDayDate.IsWeekend() ; bool IsTimeRangeMatch = !UseAllowedRangeForMatchInMinutes.GetYesNo() || r_StopDateTime.IsGivenTimeWithinGivenTimeRange(sc.BaseDateTimeIn[sc.Index], AllowedTimeRange); if (r_StopDateTime != 0 && sc.BaseDateTimeIn[sc.Index] > r_StopDateTime && !IgnoreDate && IsTimeRangeMatch) r_PriorValue = FLT_MIN; if (r_LastUsedBarIndexForExtensionLine != -1 && r_LastUsedBarIndexForExtensionLine == sc.Index) { sc.DeleteLineUntilFutureIntersection(r_LastUsedBarIndexForExtensionLine, 0); } IsTimeRangeMatch = !UseAllowedRangeForMatchInMinutes.GetYesNo() || StartDateTime.IsGivenTimeWithinGivenTimeRange(sc.BaseDateTimeIn[sc.Index], AllowedTimeRange); //Start time encountered if (!IgnoreDate && ((sc.Index == 0 && sc.BaseDateTimeIn[sc.Index] == StartDateTime) || (sc.BaseDateTimeIn[sc.Index - 1] < StartDateTime && sc.BaseDateTimeIn[sc.Index] >= StartDateTime) ) && IsTimeRangeMatch ) { Subgraph_HorizontalLine[sc.Index] = sc.BaseData[InputData.GetInputDataIndex()][sc.Index]; r_PriorValue = Subgraph_HorizontalLine[sc.Index]; if(UseStopTime.GetYesNo()) { if(StartTime.GetTime() <= StopTime.GetTime()) r_StopDateTime.SetDateTime(sc.BaseDateTimeIn[sc.Index].GetDate(), StopTime.GetTime()); else r_StopDateTime.SetDateTime(sc.BaseDateTimeIn[sc.Index].GetDate() + 1, StopTime.GetTime()); } else if (LimitHorizontalLineFromTimeToOneDay.GetYesNo()) { SCDateTime StartDateTimeWithoutMilliseconds = StartDateTime; StartDateTimeWithoutMilliseconds.RoundToNearestSecond(); r_StopDateTime = StartDateTimeWithoutMilliseconds + SCDateTime(0, HMS_TIME(23, 59, 59)); } if (AddExtensionLinesUntilFutureIntersection.GetYesNo()) { sc.AddLineUntilFutureIntersection (sc.Index , 0 // LineIDForBar , r_PriorValue , Subgraph_ExtensionLines.PrimaryColor , Subgraph_ExtensionLines.LineWidth , Subgraph_ExtensionLines.LineStyle , false , false , "" ); r_LastUsedBarIndexForExtensionLine = sc.Index; } } if (r_PriorValue != FLT_MIN) { Subgraph_HorizontalLine[sc.Index] = r_PriorValue; } } /*============================================================================*/ SCSFExport scsf_BarsWithZeros(SCStudyInterfaceRef sc) { SCSubgraphRef Open = sc.Subgraph[0]; SCSubgraphRef High = sc.Subgraph[1]; SCSubgraphRef Low = sc.Subgraph[2]; SCSubgraphRef Last = sc.Subgraph[3]; SCSubgraphRef Volume = sc.Subgraph[4]; SCSubgraphRef OpenInterest = sc.Subgraph[5]; SCSubgraphRef OHLCAvg = sc.Subgraph[6]; SCSubgraphRef HLCAvg = sc.Subgraph[7]; SCSubgraphRef HLAvg = sc.Subgraph[8]; SCSubgraphRef BidVol = sc.Subgraph[9]; SCSubgraphRef AskVol = sc.Subgraph[10]; if (sc.SetDefaults) { sc.GraphName = "Chart Bars with Zero Values"; sc.ValueFormat = VALUEFORMAT_INHERITED; sc.GraphRegion = 0; sc.DisplayAsMainPriceGraph = true; sc.GraphUsesChartColors = true; sc.GraphDrawType = GDT_OHLCBAR; sc.StandardChartHeader = 1; sc.AutoLoop = true; Open.Name = "Open"; Open.DrawStyle = DRAWSTYLE_LINE; Open.PrimaryColor = RGB(0,255,0); Open.DrawZeros = true; High.Name = "High"; High.DrawStyle = DRAWSTYLE_LINE; High.PrimaryColor = RGB(255,0,255); High.DrawZeros = true; Low.Name = "Low"; Low.DrawStyle = DRAWSTYLE_LINE; Low.PrimaryColor = RGB(255,255,0); Low.DrawZeros = true; Last.Name = "Last"; Last.DrawStyle = DRAWSTYLE_LINE; Last.PrimaryColor = RGB(255,127,0); Last.DrawZeros = true; Volume.Name = "Volume"; Volume.DrawStyle = DRAWSTYLE_IGNORE; Volume.PrimaryColor = RGB(255,0,0); Volume.DrawZeros = true; OpenInterest.Name = "# of Trades / OI"; OpenInterest.DrawStyle = DRAWSTYLE_IGNORE; OpenInterest.PrimaryColor = RGB(0,0,255); OpenInterest.DrawZeros = true; OHLCAvg.Name = "OHLC Avg"; OHLCAvg.DrawStyle = DRAWSTYLE_IGNORE; OHLCAvg.PrimaryColor = RGB(127,0,255); OHLCAvg.DrawZeros = true; HLCAvg.Name = "HLC Avg"; HLCAvg.DrawStyle = DRAWSTYLE_IGNORE; HLCAvg.PrimaryColor = RGB(0,255,255); HLCAvg.DrawZeros = true; HLAvg.Name = "HL Avg"; HLAvg.DrawStyle = DRAWSTYLE_IGNORE; HLAvg.PrimaryColor = RGB(0,127,255); HLAvg.DrawZeros = true; BidVol.Name = "Bid Vol"; BidVol.DrawStyle = DRAWSTYLE_IGNORE; BidVol.PrimaryColor = RGB(0,255,0); BidVol.DrawZeros = true; AskVol.Name = "Ask Vol"; AskVol.DrawStyle = DRAWSTYLE_IGNORE; AskVol.PrimaryColor = RGB(0,255,0); AskVol.DrawZeros = true; return; } for(int SubgraphIndex = 0; SubgraphIndex < SC_ASKVOL; SubgraphIndex++) { sc.Subgraph[SubgraphIndex][sc.Index] = sc.BaseData[SubgraphIndex][sc.Index]; } } /*============================================================================*/ SCSFExport scsf_NumbersBarsAvgVolumePerPrice(SCStudyInterfaceRef sc) { SCSubgraphRef AvgVolumePerPrice = sc.Subgraph[0]; if (sc.SetDefaults) { sc.GraphName = "Numbers Bars Avg Volume/Price Graph"; sc.GraphRegion = 1; sc.ValueFormat = VALUEFORMAT_WHOLE_NUMBER; sc.AutoLoop = true; sc.MaintainVolumeAtPriceData = 1; AvgVolumePerPrice.Name = "Avg Volume/Price"; AvgVolumePerPrice.DrawStyle = DRAWSTYLE_LINE; AvgVolumePerPrice.PrimaryColor = RGB(0,255,255); AvgVolumePerPrice.DrawZeros = true; return; } int NumPrices = sc.VolumeAtPriceForBars->GetSizeAtBarIndex(sc.Index); // Avg Vol/Price (Average Volume At Price) if (NumPrices== 0) AvgVolumePerPrice[sc.Index] = 0.0f; else AvgVolumePerPrice[sc.Index] = sc.Volume[sc.Index] / NumPrices; } /*============================================================================*/ SCSFExport scsf_InitialBalance(SCStudyInterfaceRef sc) { SCSubgraphRef IBHExt6 = sc.Subgraph[0]; SCSubgraphRef IBHExt5 = sc.Subgraph[1]; SCSubgraphRef IBHExt4 = sc.Subgraph[2]; SCSubgraphRef IBHExt3 = sc.Subgraph[3]; SCSubgraphRef IBHExt2 = sc.Subgraph[4]; SCSubgraphRef IBHExt1 = sc.Subgraph[5]; SCSubgraphRef IBHigh = sc.Subgraph[6]; SCSubgraphRef IBMid = sc.Subgraph[7]; SCSubgraphRef IBLow = sc.Subgraph[8]; SCSubgraphRef IBLExt1 = sc.Subgraph[9]; SCSubgraphRef IBLExt2 = sc.Subgraph[10]; SCSubgraphRef IBLExt3 = sc.Subgraph[11]; SCSubgraphRef IBLExt4 = sc.Subgraph[12]; SCSubgraphRef IBLExt5 = sc.Subgraph[13]; SCSubgraphRef IBLExt6 = sc.Subgraph[14]; SCInputRef Input_IBType = sc.Input[0]; SCInputRef Input_StartTime = sc.Input[1]; SCInputRef Input_EndTime = sc.Input[2]; SCInputRef Input_NumDays = sc.Input[3]; SCInputRef Input_RoundExt = sc.Input[4]; SCInputRef Input_NumberDaysToCalculate = sc.Input[5]; SCInputRef Input_NumberOfMinutes = sc.Input[6]; SCInputRef Input_StartEndTimeMethod = sc.Input[7]; SCInputRef Input_PeriodEndAsMinutesFromSessionStart = sc.Input[8]; SCInputRef Input_Multiplier1 = sc.Input[10]; SCInputRef Input_Multiplier2 = sc.Input[11]; SCInputRef Input_Multiplier3 = sc.Input[12]; SCInputRef Input_Multiplier4 = sc.Input[13]; SCInputRef Input_Multiplier5 = sc.Input[14]; SCInputRef Input_Multiplier6 = sc.Input[15]; if (sc.SetDefaults) { sc.GraphName = "Initial Balance"; sc.DrawZeros = 0; sc.GraphRegion = 0; sc.AutoLoop = 1; sc.ScaleRangeType = SCALE_SAMEASREGION; IBHExt6.Name = "IB High Ext 6"; IBHExt6.PrimaryColor = RGB(0, 255, 0); IBHExt6.DrawStyle = DRAWSTYLE_IGNORE; IBHExt6.DrawZeros = false; IBHExt5.Name = "IB High Ext 5"; IBHExt5.PrimaryColor = RGB(0, 255, 0); IBHExt5.DrawStyle = DRAWSTYLE_IGNORE; IBHExt5.DrawZeros = false; IBHExt4.Name = "IB High Ext 4"; IBHExt4.PrimaryColor = RGB(0, 255, 0); IBHExt4.DrawStyle = DRAWSTYLE_IGNORE; IBHExt4.DrawZeros = false; IBHExt3.Name = "IB High Ext 3"; IBHExt3.PrimaryColor = RGB(0, 255, 0); IBHExt3.DrawStyle = DRAWSTYLE_IGNORE; IBHExt3.DrawZeros = false; IBHExt2.Name = "IB High Ext 2"; IBHExt2.PrimaryColor = RGB(0, 255, 0); IBHExt2.DrawStyle = DRAWSTYLE_IGNORE; IBHExt2.DrawZeros = false; IBHExt1.Name = "IB High Ext 1"; IBHExt1.PrimaryColor = RGB(0, 255, 0); IBHExt1.DrawStyle = DRAWSTYLE_IGNORE; IBHExt1.DrawZeros = false; IBHigh.Name = "IB High"; IBHigh.PrimaryColor = RGB(128, 255, 128); IBHigh.DrawStyle = DRAWSTYLE_DASH; IBHigh.DrawZeros = false; IBMid.Name = "IB Mid"; IBMid.PrimaryColor = RGB(255, 255, 255); IBMid.DrawStyle = DRAWSTYLE_DASH; IBMid.DrawZeros = false; IBLow.Name = "IB Low"; IBLow.PrimaryColor = RGB(255, 128, 128); IBLow.DrawStyle = DRAWSTYLE_DASH; IBLow.DrawZeros = false; IBLExt1.Name = "IB Low Ext 1"; IBLExt1.PrimaryColor = RGB(255, 0, 0); IBLExt1.DrawStyle = DRAWSTYLE_IGNORE; IBLExt1.DrawZeros = false; IBLExt2.Name = "IB Low Ext 2"; IBLExt2.PrimaryColor = RGB(255, 0, 0); IBLExt2.DrawStyle = DRAWSTYLE_IGNORE; IBLExt2.DrawZeros = false; IBLExt3.Name = "IB Low Ext 3"; IBLExt3.PrimaryColor = RGB(255, 0, 0); IBLExt3.DrawStyle = DRAWSTYLE_IGNORE; IBLExt3.DrawZeros = false; IBLExt4.Name = "IB Low Ext 4"; IBLExt4.PrimaryColor = RGB(255, 0, 0); IBLExt4.DrawStyle = DRAWSTYLE_IGNORE; IBLExt4.DrawZeros = false; IBLExt5.Name = "IB Low Ext 5"; IBLExt5.PrimaryColor = RGB(255, 0, 0); IBLExt5.DrawStyle = DRAWSTYLE_IGNORE; IBLExt5.DrawZeros = false; IBLExt6.Name = "IB Low Ext 6"; IBLExt6.PrimaryColor = RGB(255, 0, 0); IBLExt6.DrawStyle = DRAWSTYLE_IGNORE; IBLExt6.DrawZeros = false; // Inputs Input_IBType.Name = "Initial Balance Type"; Input_IBType.SetCustomInputStrings("Daily;Weekly;Weekly Include Sunday;Intraday"); Input_IBType.SetCustomInputIndex(0); Input_StartTime.Name = "Start Time"; Input_StartTime.SetTime(HMS_TIME(9, 30, 0)); Input_EndTime.Name = "End Time"; Input_EndTime.SetTime(HMS_TIME(10, 29, 59)); Input_NumDays.Name = "Weekly: Number of Days"; Input_NumDays.SetInt(2); Input_NumDays.SetIntLimits(1, 5); Input_NumberOfMinutes.Name = "Intraday: Number of Minutes"; Input_NumberOfMinutes.SetInt(15); Input_RoundExt.Name = "Round Extensions to TickSize"; Input_RoundExt.SetYesNo(1); Input_NumberDaysToCalculate.Name = "Number of Days to Calculate"; Input_NumberDaysToCalculate.SetInt(100000); Input_NumberDaysToCalculate.SetIntLimits(1,INT_MAX); Input_StartEndTimeMethod.Name = "Start End Time Method"; Input_StartEndTimeMethod.SetCustomInputStrings("Use Start/End Time;Use Session Start Time and Minutes From Start"); Input_StartEndTimeMethod.SetCustomInputIndex(0); Input_PeriodEndAsMinutesFromSessionStart.Name = "Period End As Minutes from Session Start"; Input_PeriodEndAsMinutesFromSessionStart.SetInt(30); Input_Multiplier1.Name = "Extension Multiplier 1"; Input_Multiplier1.SetFloat(.5f); Input_Multiplier2.Name = "Extension Multiplier 2"; Input_Multiplier2.SetFloat(1.0f); Input_Multiplier3.Name = "Extension Multiplier 3"; Input_Multiplier3.SetFloat(1.5f); Input_Multiplier4.Name = "Extension Multiplier 4"; Input_Multiplier4.SetFloat(2.0f); Input_Multiplier5.Name = "Extension Multiplier 5"; Input_Multiplier5.SetFloat(2.5f); Input_Multiplier6.Name = "Extension Multiplier 6"; Input_Multiplier6.SetFloat(3.0f); return; } // Persist vars int& PeriodFirstIndex = sc.GetPersistentInt(1); SCDateTime& PeriodStartDateTime = sc.GetPersistentSCDateTime(1); SCDateTime& PeriodEndDateTime = sc.GetPersistentSCDateTime(2); float& PeriodHigh = sc.GetPersistentFloat(1); float& PeriodLow = sc.GetPersistentFloat(2); float& PeriodMid = sc.GetPersistentFloat(3); float& PeriodHighExt1 = sc.GetPersistentFloat(4); float& PeriodHighExt2 = sc.GetPersistentFloat(5); float& PeriodHighExt3 = sc.GetPersistentFloat(6); float& PeriodHighExt4 = sc.GetPersistentFloat(7); float& PeriodHighExt5 = sc.GetPersistentFloat(8); float& PeriodHighExt6 = sc.GetPersistentFloat(9); float& PeriodLowExt1 = sc.GetPersistentFloat(10); float& PeriodLowExt2 = sc.GetPersistentFloat(11); float& PeriodLowExt3 = sc.GetPersistentFloat(12); float& PeriodLowExt4 = sc.GetPersistentFloat(13); float& PeriodLowExt5 = sc.GetPersistentFloat(14); float& PeriodLowExt6 = sc.GetPersistentFloat(15); // Reset persistent variables upon full calculation if (sc.Index == 0) { PeriodFirstIndex = -1; PeriodStartDateTime = 0; PeriodEndDateTime = 0; PeriodHigh = -FLT_MAX; PeriodLow = FLT_MAX; } SCDateTime LastBarDateTime = sc.BaseDateTimeIn[sc.ArraySize-1]; SCDateTime FirstCalculationDate = LastBarDateTime.GetDate() - (Input_NumberDaysToCalculate.GetInt()-1); SCDateTime CurrentBarDateTime = sc.BaseDateTimeIn[sc.Index]; SCDateTime PrevBarDateTime; if (sc.Index > 0) PrevBarDateTime = sc.BaseDateTimeIn[sc.Index-1]; if (CurrentBarDateTime.GetDate() < FirstCalculationDate) // Limit calculation to specified number of days back return; bool Daily = Input_IBType.GetIndex() == 0; bool Weekly = Input_IBType.GetIndex() == 1 || Input_IBType.GetIndex() == 2; bool Intraday = Input_IBType.GetIndex() == 3; bool IncludeSunday = Input_IBType.GetIndex() == 2; // check if starting new period, reset vars SCDateTime StartDateTime = CurrentBarDateTime; if (Input_StartEndTimeMethod.GetIndex() == 0) StartDateTime.SetTime(Input_StartTime.GetTime()); else StartDateTime.SetTime(sc.StartTimeOfDay); if (Weekly) { int PeriodStartDayOfWeek = IncludeSunday ? SUNDAY : MONDAY; int DayOfWeek = StartDateTime.GetDayOfWeek(); if (DayOfWeek != PeriodStartDayOfWeek) StartDateTime += ((7 - DayOfWeek + PeriodStartDayOfWeek) * DAYS); } if (PrevBarDateTime < StartDateTime && CurrentBarDateTime >= StartDateTime) { PeriodFirstIndex = sc.Index; PeriodHigh = -FLT_MAX; PeriodLow = FLT_MAX; PeriodStartDateTime = StartDateTime; PeriodEndDateTime = PeriodStartDateTime; if (Input_StartEndTimeMethod.GetIndex() == 0) PeriodEndDateTime.SetTime(Input_EndTime.GetTime()); else { PeriodEndDateTime.SetTime(static_cast(sc.StartTimeOfDay + Input_PeriodEndAsMinutesFromSessionStart.GetInt()*SECONDS_PER_MINUTE - 1*SECONDS)); } if (Daily || Intraday) { if (PeriodEndDateTime <= PeriodStartDateTime) PeriodEndDateTime += (1 * DAYS); } else if (Weekly) { int PeriodEndDayOfWeek = IncludeSunday ? Input_NumDays.GetInt() - 1 : Input_NumDays.GetInt(); int DayOfWeek = PeriodEndDateTime.GetDayOfWeek(); if (DayOfWeek != PeriodEndDayOfWeek) PeriodEndDateTime += ((PeriodEndDayOfWeek - DayOfWeek) * DAYS); } } // Check end of period if (PeriodFirstIndex >= 0) { // Check start of new intraday period if (Intraday) { SCDateTime IntradayEndDateTime = PeriodStartDateTime + Input_NumberOfMinutes.GetInt() * MINUTES - 1 * SECONDS; if (PrevBarDateTime < IntradayEndDateTime && CurrentBarDateTime > IntradayEndDateTime) { PeriodFirstIndex = sc.Index; PeriodStartDateTime += Input_NumberOfMinutes.GetInt() * MINUTES; PeriodHigh = -FLT_MAX; PeriodLow = FLT_MAX; } } if (CurrentBarDateTime > PeriodEndDateTime) { PeriodFirstIndex = -1; if (Intraday) { PeriodHigh = -FLT_MAX; PeriodLow = FLT_MAX; } } } // Collecting data, back propagate if changed if (PeriodFirstIndex >= 0) { bool Changed = false; if (sc.High[sc.Index] > PeriodHigh) { PeriodHigh = sc.High[sc.Index]; Changed = true; } if (sc.Low[sc.Index] < PeriodLow) { PeriodLow = sc.Low[sc.Index]; Changed = true; } if (Changed) { PeriodMid = (PeriodHigh + PeriodLow) / 2.0f; float Range = PeriodHigh - PeriodLow; PeriodHighExt1 = PeriodHigh + Input_Multiplier1.GetFloat() * Range; PeriodHighExt2 = PeriodHigh + Input_Multiplier2.GetFloat() * Range; PeriodHighExt3 = PeriodHigh + Input_Multiplier3.GetFloat() * Range; PeriodHighExt4 = PeriodHigh + Input_Multiplier4.GetFloat() * Range; PeriodHighExt5 = PeriodHigh + Input_Multiplier5.GetFloat() * Range; PeriodHighExt6 = PeriodHigh + Input_Multiplier6.GetFloat() * Range; PeriodLowExt1 = PeriodLow - Input_Multiplier1.GetFloat() * Range; PeriodLowExt2 = PeriodLow - Input_Multiplier2.GetFloat() * Range; PeriodLowExt3 = PeriodLow - Input_Multiplier3.GetFloat() * Range; PeriodLowExt4 = PeriodLow - Input_Multiplier4.GetFloat() * Range; PeriodLowExt5 = PeriodLow - Input_Multiplier5.GetFloat() * Range; PeriodLowExt6 = PeriodLow - Input_Multiplier6.GetFloat() * Range; if (Input_RoundExt.GetYesNo()) { PeriodHighExt1 = sc.RoundToTickSize(PeriodHighExt1, sc.TickSize); PeriodHighExt2 = sc.RoundToTickSize(PeriodHighExt2, sc.TickSize); PeriodHighExt3 = sc.RoundToTickSize(PeriodHighExt3, sc.TickSize); PeriodHighExt4 = sc.RoundToTickSize(PeriodHighExt4, sc.TickSize); PeriodHighExt5 = sc.RoundToTickSize(PeriodHighExt5, sc.TickSize); PeriodHighExt6 = sc.RoundToTickSize(PeriodHighExt6, sc.TickSize); PeriodLowExt1 = sc.RoundToTickSize(PeriodLowExt1, sc.TickSize); PeriodLowExt2 = sc.RoundToTickSize(PeriodLowExt2, sc.TickSize); PeriodLowExt3 = sc.RoundToTickSize(PeriodLowExt3, sc.TickSize); PeriodLowExt4 = sc.RoundToTickSize(PeriodLowExt4, sc.TickSize); PeriodLowExt5 = sc.RoundToTickSize(PeriodLowExt5, sc.TickSize); PeriodLowExt6 = sc.RoundToTickSize(PeriodLowExt6, sc.TickSize); } for (int Index = PeriodFirstIndex; Index < sc.Index; Index++) { IBHigh[Index] = PeriodHigh; IBLow[Index] = PeriodLow; IBMid[Index] = PeriodMid; IBHExt1[Index] = PeriodHighExt1; IBHExt2[Index] = PeriodHighExt2; IBHExt3[Index] = PeriodHighExt3; IBHExt4[Index] = PeriodHighExt4; IBHExt5[Index] = PeriodHighExt5; IBHExt6[Index] = PeriodHighExt6; IBLExt1[Index] = PeriodLowExt1; IBLExt2[Index] = PeriodLowExt2; IBLExt3[Index] = PeriodLowExt3; IBLExt4[Index] = PeriodLowExt4; IBLExt5[Index] = PeriodLowExt5; IBLExt6[Index] = PeriodLowExt6; } sc.EarliestUpdateSubgraphDataArrayIndex = PeriodFirstIndex; } } // Plot current values if (PeriodLow != FLT_MAX) { IBHigh[sc.Index] = PeriodHigh; IBLow[sc.Index] = PeriodLow; IBMid[sc.Index] = PeriodMid; IBHExt1[sc.Index] = PeriodHighExt1; IBHExt2[sc.Index] = PeriodHighExt2; IBHExt3[sc.Index] = PeriodHighExt3; IBHExt4[sc.Index] = PeriodHighExt4; IBHExt5[sc.Index] = PeriodHighExt5; IBHExt6[sc.Index] = PeriodHighExt6; IBLExt1[sc.Index] = PeriodLowExt1; IBLExt2[sc.Index] = PeriodLowExt2; IBLExt3[sc.Index] = PeriodLowExt3; IBLExt4[sc.Index] = PeriodLowExt4; IBLExt5[sc.Index] = PeriodLowExt5; IBLExt6[sc.Index] = PeriodLowExt6; } } /*============================================================================*/ SCSFExport scsf_RenkoVisualOpenCloseValues(SCStudyInterfaceRef sc) { SCSubgraphRef RenkoOpen = sc.Subgraph[0]; SCSubgraphRef RenkoClose = sc.Subgraph[1]; if (sc.SetDefaults) { sc.GraphName = "Renko Visual Open/Close Values"; sc.DrawZeros = 0; sc.GraphRegion = 0; sc.AutoLoop = 1; sc.ScaleRangeType = SCALE_SAMEASREGION; RenkoOpen.Name = "Renko Open"; RenkoOpen.PrimaryColor = RGB(255, 255, 255); RenkoOpen.LineWidth = 3; RenkoOpen.DrawStyle = DRAWSTYLE_LEFT_PRICE_BAR_DASH; RenkoOpen.DrawZeros = false; RenkoClose.Name = "Renko Close"; RenkoClose.PrimaryColor = RGB(255, 255, 255); RenkoClose.LineWidth = 3; RenkoClose.DrawStyle = DRAWSTYLE_RIGHT_PRICE_BAR_DASH; RenkoClose.DrawZeros = false; return; } if (sc.RenkoTicksPerBar != 0) { RenkoOpen[sc.Index] = sc.BaseData[SC_RENKO_OPEN][sc.Index]; RenkoClose[sc.Index] = sc.BaseData[SC_RENKO_CLOSE][sc.Index]; } } /*============================================================================*/ SCSFExport scsf_StochasticPercentile(SCStudyInterfaceRef sc) { SCSubgraphRef StochasticSubgraph = sc.Subgraph[0]; SCSubgraphRef StochasticAverageSubgraph = sc.Subgraph[1]; SCSubgraphRef Line1 = sc.Subgraph[2]; SCSubgraphRef Line2 = sc.Subgraph[3]; SCInputRef InputData = sc.Input[0]; SCInputRef StochasticLength = sc.Input[1]; SCInputRef MovingAverageLength = sc.Input[2]; SCInputRef Line1Value = sc.Input[3]; SCInputRef Line2Value = sc.Input[4]; if (sc.SetDefaults) { sc.GraphName = "Stochastic - Percentile"; sc.ValueFormat = 2; StochasticSubgraph.Name = "Stochastic%"; StochasticSubgraph.DrawStyle = DRAWSTYLE_LINE; StochasticSubgraph.PrimaryColor = RGB(0,255,0); StochasticSubgraph.DrawZeros = true; StochasticAverageSubgraph.Name = "Average"; StochasticAverageSubgraph.DrawStyle = DRAWSTYLE_LINE; StochasticAverageSubgraph.PrimaryColor = RGB(255, 127, 0); StochasticAverageSubgraph.DrawZeros = true; Line1.Name = "Line1"; Line1.DrawStyle = DRAWSTYLE_LINE; Line1.PrimaryColor = RGB(255, 255, 0); Line1.DrawZeros = true; Line2.Name = "Line2"; Line2.DrawStyle = DRAWSTYLE_LINE; Line2.PrimaryColor = RGB(0, 0, 255); Line2.DrawZeros = true; InputData.Name = "Input Data"; InputData.SetInputDataIndex(SC_LAST); StochasticLength.Name = "Length"; StochasticLength.SetInt(10); StochasticLength.SetIntLimits(1,MAX_STUDY_LENGTH); MovingAverageLength.Name = "Moving Average Length"; MovingAverageLength.SetInt(10); MovingAverageLength.SetIntLimits(1, MAX_STUDY_LENGTH); Line1Value.Name = "Line 1 Value"; Line1Value.SetFloat(20); Line2Value.Name = "Line 2 Value"; Line2Value.SetFloat(80); sc.AutoLoop = false; return; } std::vector AscendingValues; SCFloatArrayRef DataArray = sc.BaseData[InputData.GetInputDataIndex()]; sc.DataStartIndex = StochasticLength.GetInt() - 1; for (int CurrentIndex = sc.UpdateStartIndex; CurrentIndex < sc.ArraySize; CurrentIndex++) { AscendingValues.clear(); int FirstIndex = CurrentIndex - StochasticLength.GetInt() + 1; for (int BarIndex = FirstIndex; BarIndex <= CurrentIndex; BarIndex++) { AscendingValues.push_back(DataArray[BarIndex]); } std::sort(AscendingValues.begin(), AscendingValues.end()); float CurrentPrice = DataArray[CurrentIndex]; int AscendingValuesSize = static_cast(AscendingValues.size()); int AscendingValuesIndex = 0; for(; AscendingValuesIndex < AscendingValuesSize; AscendingValuesIndex++) { if (CurrentPrice == AscendingValues[AscendingValuesIndex]) break; if (AscendingValuesIndex == AscendingValuesSize - 1) break; } StochasticSubgraph[CurrentIndex] = 100.0f*AscendingValuesIndex/(StochasticLength.GetInt() - 1); sc.SimpleMovAvg(StochasticSubgraph, StochasticAverageSubgraph, CurrentIndex, MovingAverageLength.GetInt()); Line1[CurrentIndex] = Line1Value.GetFloat(); Line2[CurrentIndex] = Line2Value.GetFloat(); } return; }