Login Page - Create Account

Support Board


Date/Time: Sun, 22 Dec 2024 12:42:47 +0000



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

View Count: 4504

[2015-04-20 00:44:31]
eagle - Posts: 92
In an ACSIL custom study, how can I run a partial code block only once per bar, while the rest of the code runs more often?

Thanks

[2015-04-20 04:28:43]
ejtrader - Posts: 688
You can try this..

int &lastIndex = sc.GetPersistentInt(0);

if (sc.UpdateStartIndex == 0) {
lastIndex = -1;
}

// Place all code that needs to execute all ticks here
{......}

if (lastIndex == sc.Index) {
return;
}

lastIndex = sc.Index;

// Place all code that needs to execute only once per bar below - this would get executed on first tick of each bar
{....}


Date Time Of Last Edit: 2018-12-13 03:48:54
[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;
      }
    }
  }
}

[2015-04-20 05:52:19]
eagle - Posts: 92
1. In the code of Post #3, is the value of "sc.OnExternalDataImmediateStudyCall", that's set in SECTION 2, persistent across calls to the function?
[2015-04-20 06:36:11]
eagle - Posts: 92
I moved the assignment setting of "sc.OnExternalDataImmediateStudyCall" to run only on startup:

if (Index == 0) {        // Startups and recalculations.

    // Set the value of Fast Update for Trade Data.
    sc.OnExternalDataImmediateStudyCall = FastUpdate.GetIndex();

    // Initialize the LastIndexProcessed persistent variable.
    LastIndexProcessed = -1;

    // Don't process further on startups nor recalculations.
    return;
  }

2. Will this setting of "sc.OnExternalDataImmediateStudyCall" be persistent across calls to the study function?
[2015-04-20 13:31:31]
ejtrader - Posts: 688
What would be the difference between using "sc.PersistVars->Integers[0]" or "sc.PersistVars->i1"?

There is no difference between using either of them (or the way I have mentioned above in the code).

Related to other question - OnExternalDataImmediateStudyCall - refer to the document here and code according to your need :)

http://www.sierrachart.com/index.php?page=doc/doc_ACSIL_Members_Variables_And_Arrays.html#scOnExternalDataImmediateStudyCall

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

Login

Login Page - Create Account