Login Page - Create Account

Support Board


Date/Time: Sat, 01 Feb 2025 10:03:33 +0000



[Programming Help] - Adjusting Volume By Price studies based on Zig Zag or Swings (intraday)

View Count: 1589

[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);
}

To post a message in this thread, you need to log in with your Sierra Chart account:

Login

Login Page - Create Account