Login Page - Create Account

Support Board


Date/Time: Sun, 22 Dec 2024 12:14:17 +0000



Post From: ACSIL - How to run part of code only once per bar

[2015-04-20 05:29:31]
eagle - Posts: 92
Thanks, ejtrader. BTW, a post of yours from a couple years ago was part of my reference material.

Thinking and thinking about persistent variables, I finally took a stab at it (before I saw your post).

What would be the difference between using "sc.PersistVars->Integers[0]" or "sc.PersistVars->i1"?

Do you (or anyone else) see any errors or inefficiencies in the following code?


#include "sierrachart.h"

SCDLLName("Bid Ask Ratio Alert")

SCSFExport scsf_BidAskRatioAlert(SCStudyInterfaceRef sc)
{
  SCSubgraphRef Buy = sc.Subgraph[0];
  SCSubgraphRef Sell = sc.Subgraph[1];

  SCInputRef RatioThreshold = sc.Input[0];
  SCInputRef ArrowOffsetType = sc.Input[1];
  SCInputRef ArrowOffsetValue = sc.Input[2];
  SCInputRef FastUpdate = sc.Input[3];

  // SECTION 1: *** Configuration Variables and Defaults ***

  if (sc.SetDefaults)
  {  
    sc.GraphName = "Bid Ask Ratio Alert";
    sc.StudyDescription = "Draw arrows when the ratio exceeds the threshold.";

    Buy.Name = "Buy Alert Arrow";
    Buy.DrawStyle = DRAWSTYLE_ARROWUP;
    Buy.PrimaryColor = RGB(0, 255, 0);  // Green
    Buy.LineWidth = 4;      // Width of arrow

    Sell.Name = "Sell Alert Arrow";
    Sell.DrawStyle = DRAWSTYLE_ARROWDOWN;
    Sell.PrimaryColor = RGB(255, 0, 0);  // Red
    Sell.LineWidth = 4;      // Width of arrow

    RatioThreshold.Name = "Bid/Ask Size Ratio Threshold";
    RatioThreshold.SetFloat(2.5);

    ArrowOffsetType.Name = "Alert Arrow Offset Specified As";
    ArrowOffsetType.SetCustomInputStrings("Tick Offset;Percentage of Chart;Percentage of Price");
    ArrowOffsetType.SetCustomInputIndex(1);

    ArrowOffsetValue.Name = "Alert Arrow Offset";
    ArrowOffsetValue.SetFloat(5.2);

    FastUpdate.Name = "Fast Update for Trade Data";
    FastUpdate.SetCustomInputStrings("Disable;Enable");
    FastUpdate.SetCustomInputIndex(0);

    sc.GraphRegion = 0;      // Main chart region
    sc.DrawZeros= 0;

    // Enforce Fast Update for Trade Data Disable on startup.
    sc.OnExternalDataImmediateStudyCall = 0;

    // Looping is not needed. Only the current bar is processed.
    sc.AutoLoop = 0;
    sc.FreeDLL = 0;

    return;
  }

  // SECTION 2: *** Study Function Variables ***

  int Index = sc.Index;        // Set Index to the current bar.
  int &LastIndexProcessed = sc.PersistVars->i1;
  float &ArrowOffset = sc.PersistVars->f1;

  // Don't process on startups nor recalculations.
  if (Index == 0) {
    LastIndexProcessed = -1;
    return;
  }

  // Process this block only once per bar.
  if (Index > LastIndexProcessed) {
    sc.OnExternalDataImmediateStudyCall = FastUpdate.GetIndex();

    // Calculate alert arrow offset.
    int ArrowOffsetTypeIndex = ArrowOffsetType.GetIndex();
    float OffsetValue = ArrowOffsetValue.GetFloat();
    float ChartHigh, ChartLow;
    sc.GetMainGraphVisibleHighAndLow(ChartHigh, ChartLow);

    if (ArrowOffsetTypeIndex == 0) {
      ArrowOffset = OffsetValue * sc.TickSize;
      }
    else if (ArrowOffsetTypeIndex == 1) {
      ArrowOffset = OffsetValue * (ChartHigh - ChartLow) * 0.005f;
      }
    else {
      ArrowOffset = OffsetValue * sc.Open[Index] * 0.00005f;
      }

    // Remove all arrows from the previous bar.
    Buy[Index -1] = 0;
    Sell[Index -1] = 0;

    LastIndexProcessed = Index;
  }

  // SECTION 3: *** Data Processing ***

  if (sc.ServerConnectionState == 3) {    // Connected to data feed.
    int AskSize = sc.AskSize;
    int BidSize = sc.BidSize;

    if ((AskSize > 0) && (BidSize > 0)) {  // Prevent divide by zero.
      if (BidSize > AskSize) {
        if (((float) BidSize / (float) AskSize) > RatioThreshold.GetFloat()) {
          // Remove any down arrow from the current bar.
          Sell[Index] = 0;
          // Place an up arrow below the low of the current bar.
          Buy[Index] = sc.Low[Index] - ArrowOffset;
        }
        else {
          // Remove all arrows from the current bar.
          Buy[Index] = 0;
          Sell[Index] = 0;
        }
      }
      else if (AskSize > BidSize) {
        if (((float) AskSize / (float) BidSize) > RatioThreshold.GetFloat()) {
          // Remove any up arrow from the current bar.
          Buy[Index] = 0;
          // Place a down arrow above the high of the current bar.
          Sell[Index] = sc.High[Index] + ArrowOffset;
        }
        else {
          // Remove all arrows from the current bar.
          Buy[Index] = 0;
          Sell[Index] = 0;
        }
      }
      else {
        // Remove all arrows from the current bar.
        Buy[Index] = 0;
        Sell[Index] = 0;
      }
    }
  }
}