Support Board
Date/Time: Sat, 01 Feb 2025 12:51:11 +0000
Post From: Adjusting Volume By Price studies based on Zig Zag or Swings (intraday)
[2019-07-06 17:32:52] |
QnReally - Posts: 181 |
To build the DLL: There are variations in how you can build the DLL to use this study. I used Visual Studio to build my DLL but unfortunately I cannot provide any support with that. I'd refer you to Sierra Chart's standards ways of producing the DLL. You will need to download boost (https://www.boost.org/users/download/) to compile the study as it is written. How to use the study once you have the DLL built: 1) You will need a zig zag study in your chart 2) Add as many Volume By Price studies and set the Volume Graph Period Type to From Start Date-Time to End Date-Time. 3) Add this study and specify the Zig Zag study and the study IDs of the VBPs as a CSV in the Input section. #include "C:\\SierraChart\ACS_Source\sierrachart.h"
#include <boost/algorithm/string.hpp> // https://www.boost.org/users/download/ // Governs the per second rate of execution. The lastCallTime must have millisecond precision. // maxRate specifies maximum number of executions per second. 0.1 => once every 10 seconds. 10 => once every 100 ms. inline bool rateOfExecGovernorCE(SCStudyGraphRef sc, SCDateTime lastCallTime, float maxRate) { SCDateTime cTime = sc.CurrentSystemDateTimeMS; if (1.0f / ((cTime - lastCallTime) * 86400.0f) < maxRate) return true; return false; } // maxRate: 1 => Once per minute, 10 => 10 execs per minute or once every 6 seconds, 0.1 => Once every 10 minutes inline bool maxExecFPMCE(SCStudyGraphRef sc, SCDateTime lastCallTime, float maxRate) { // Max running frequency per minute return (rateOfExecGovernorCE(sc, lastCallTime, maxRate / 60.0f)); } SCSFExport scsf_AdjustVBPInputsForZZSwingsCE(SCStudyInterfaceRef sc) { SCInputRef vbpUpdateVBPCount = sc.Input[1]; SCInputRef vbpVBPList = sc.Input[3]; SCInputRef ZZStudy = sc.Input[4]; SCInputRef UpdateSpeed = sc.Input[5]; SCDateTime& lastCallTime = sc.GetPersistentSCDateTime(1); if (sc.SetDefaults) { sc.GraphName = "Adjust VBP Inputs to Match ZZ Swings CE"; // Community Edition sc.StudyDescription = "The Volume By Price drawings are drawn for the last few swings. This functionality uses the zigzag study to adjust VBP SCInputs."; sc.GraphRegion = 0; sc.ScaleRangeType = SCALE_SAMEASREGION; unsigned short DisplayOrder = 1; vbpUpdateVBPCount.Name = "Number of VBPs to update"; vbpUpdateVBPCount.SetDescription("The number of VBPs to update starting at the end of the chart going backwards."); vbpUpdateVBPCount.SetInt(0); vbpUpdateVBPCount.SetIntLimits(0, 64); vbpUpdateVBPCount.DisplayOrder = DisplayOrder++; vbpVBPList.Name = "List of VBPs (csv)"; vbpVBPList.SetDescription("The list of comma-separated VBP IDs starting at the last time period going backwards.\ Need Volume By Price studies that have <b>Volume Graph Period Type</b> set to <b>From Start Date-Time to End Date-Time</b>."); vbpVBPList.SetString(""); vbpVBPList.DisplayOrder = DisplayOrder++; ZZStudy.Name = "Zig Zag study for Labels"; ZZStudy.SetDescription("Typically a larger Zig Zag should be used to for displaying the labels in order not to make the chart busy."); ZZStudy.SetStudyID(0); ZZStudy.DisplayOrder = DisplayOrder++; UpdateSpeed.Name = "Update frequency per minute"; UpdateSpeed.SetDescription("Maximum update frequency per minute."); UpdateSpeed.SetFloat(1.0f); UpdateSpeed.SetFloatLimits(0.0f, 100.0f); UpdateSpeed.DisplayOrder = DisplayOrder++; sc.DrawZeros = 0; sc.AutoLoop = 0; sc.FreeDLL = 0; return; } if (sc.HideStudy) return; if (maxExecFPMCE(sc, lastCallTime, UpdateSpeed.GetFloat())) { lastCallTime = sc.CurrentSystemDateTimeMS; } else { return; } SCFloatArray ZZL; std::vector<std::string> vStudyStr; std::string line = vbpVBPList.GetString(); boost::split(vStudyStr, line, boost::is_any_of(",")); int si = 0; // Study index if (vStudyStr.size() == 0) return; sc.GetStudyExtraArrayFromChartUsingID(sc.ChartNumber, ZZStudy.GetStudyID(), 0, 0, ZZL); int ri = sc.ArraySize - 1; int TDate = sc.GetTradingDayDate(sc.BaseDateTimeIn.DateAt(ri)); SCDateTime lastBarDate = sc.GetEndingDateTimeForBarIndex(ri); lastBarDate.RoundDateTimeDownToMinute(); lastBarDate += 1 * MINUTES; int lastTDate = TDate; int zzPeakCount = 0; int oldDate; double oldTime; bool SCInputModified = false; while (ri >= 0 && zzPeakCount < vbpUpdateVBPCount.GetInt()) { while (ri >= 0 && ZZL[ri] == 0.0f) ri--; if (ri < 0) break; // Adjust one VBP's start/end date/time { int study = atoi(vStudyStr[si].c_str()); double date, time; { time = std::modf(sc.BaseDateTimeIn[ri], &date); sc.GetChartStudyInputInt(sc.ChartNumber, study, 36, oldDate); if (int(date) != oldDate) { sc.SetChartStudyInputInt(sc.ChartNumber, study, 36, int(date)); SCInputModified = true; } sc.GetChartStudyInputFloat(sc.ChartNumber, study, 38, oldTime); SCDateTime scdTime = time, scdOldTime = oldTime; scdTime.RoundDateTimeDownToSecond(); scdOldTime.RoundDateTimeDownToSecond(); if (scdTime != scdOldTime) { sc.SetChartStudyInputFloat(sc.ChartNumber, study, 38, time); SCInputModified = true; } } { time = std::modf(lastBarDate, &date); sc.GetChartStudyInputInt(sc.ChartNumber, study, 39, oldDate); if (int(date) != oldDate) { sc.SetChartStudyInputInt(sc.ChartNumber, study, 39, int(date)); SCInputModified = true; } sc.GetChartStudyInputFloat(sc.ChartNumber, study, 40, oldTime); SCDateTime scdTime = time, scdOldTime = oldTime; scdTime.RoundDateTimeDownToSecond(); scdOldTime.RoundDateTimeDownToSecond(); if (scdTime != scdOldTime) { sc.SetChartStudyInputFloat(sc.ChartNumber, study, 40, time); SCInputModified = true; } } lastBarDate = sc.GetEndingDateTimeForBarIndex(ri) - MILLISECONDS; } zzPeakCount++; TDate = sc.GetTradingDayDate(sc.BaseDateTimeIn.DateAt(ri)); if (TDate != lastTDate) break; si++; if (si >= vStudyStr.size()) break; lastTDate = TDate; ri--; } if (SCInputModified) sc.RecalculateChart(sc.ChartNumber); } |