Login Page - Create Account

Support Board


Date/Time: Sat, 18 May 2024 22:26:46 +0000



Post From: Sock Renko

[2020-06-15 15:18:05]
Ackin - Posts: 1865
/******************************************************
* A version of the renko chart study for Sierra Chart.*
* By Sock 2009                    *
* windysock@gmail.com *
******************************************************/
SCSFExport scsf_SockRenkoChart(SCStudyInterfaceRef sc)
{
  SCFloatArrayRef InOpen = sc.Open;
  SCFloatArrayRef InHigh = sc.High;
  SCFloatArrayRef InLow = sc.Low;
  SCFloatArrayRef InClose = sc.Close;
  SCFloatArrayRef InVolume = sc.Volume;
  SCSubgraphRef OutOpen = sc.Subgraph[RK_OPEN];         
  SCSubgraphRef OutHigh = sc.Subgraph[RK_HIGH];         
  SCSubgraphRef OutLow = sc.Subgraph[RK_LOW];       
  SCSubgraphRef OutClose = sc.Subgraph[RK_LAST];       
  SCSubgraphRef OutVolume = sc.Subgraph[RK_VOLUME];     
  SCSubgraphRef OutBoxSize = sc.Subgraph[RK_BOXSIZE];   
  SCSubgraphRef OutOCR = sc.Subgraph[RK_OCR];       
  SCSubgraphRef OutOC = sc.Subgraph[RK_OC];       
  SCSubgraphRef OutColorCount = sc.Subgraph[RK_COLORCNT];
  SCSubgraphRef OutColor = sc.Subgraph[RK_COLOR];
  SCSubgraphRef OutRenkoClose = sc.Subgraph[RK_RCLOSE];
  SCSubgraphRef OutHL = sc.Subgraph[RK_HL];
  SCSubgraphRef OutHLC = sc.Subgraph[RK_HLC];
  SCSubgraphRef OutOHLC = sc.Subgraph[RK_OHLC];

  // Set configuration variables

  if (sc.SetDefaults)
  {
    // Set the defaults  
    sc.GraphName = "Sock Renko Chart";
    sc.StudyDescription = "Renko chart study by Sock. Comments to windysock@gmail.com";
    sc.IsCustomChart = 1;  
    sc.GraphRegion = 0;     
    sc.DrawZeros = 0;
    sc.GraphDrawType = GDT_CANDLESTICK_BODY_ONLY;
    sc.StandardChartHeader = 1;
    sc.AutoLoop = 0;
    sc.FreeDLL = 0;

    // Subgraphs    
    OutOpen.Name = "Open";
    OutOpen.PrimaryColor = COLOR_GREEN;
    OutHigh.Name = "High";
    OutHigh.PrimaryColor = COLOR_GREEN;
    OutLow.Name = "Low";
    OutLow.PrimaryColor = COLOR_RED;
    OutClose.Name = "Close";
    OutClose.PrimaryColor = COLOR_RED;
    OutVolume.Name = "Volume";
    OutRenkoClose.Name = "R-Renko Close";
    OutBoxSize.Name = "Box Size";
    OutOCR.Name = "OCR Avg";
    OutOC.Name = "OC Avg";
    OutColorCount.Name = "Same colour box count";
    OutColor.Name = "Box colour";
    OutHL.Name = "HL Avg";
    OutHLC.Name = "HLC Avg";
    OutOHLC.Name = "OHLC Avg";
    // Inputs    
    sc.Input[0].Name = "Fixed box size";
    sc.Input[0].SetFloat(1.0f);
    sc.Input[1].Name = "Start chart on multiples of:";
    sc.Input[1].SetFloat(1.0f);
    sc.Input[2].Name = "Display wicks & tails:";
    sc.Input[2].SetYesNo(0);
    sc.Input[3].Name = "Set box size using ATR from another chart?:";
    sc.Input[3].SetYesNo(0);
    sc.Input[4].Name = "ATR chart number:";
    sc.Input[4].SetInt(0);
    sc.Input[5].Name = "ATR study number:";
    sc.Input[5].SetInt(0);
    sc.Input[6].Name = "ATR subgraph number:";
    sc.Input[6].SetInt(0);
    sc.Input[7].Name = "ATR multiplier:";
    sc.Input[7].SetFloat(1.0f);
    sc.Input[8].Name = "Round ATR to nearest:";
    sc.Input[8].SetFloat(1.0f);

    return;
  }
  try {

    long i = 0;    // input index - underlying bar chart
    long o = 0;    // output index - renko chart
    long OtherIndex = 0; // other chart study index
    if (sc.BaseGraphValueFormat > 6) {
      throw "Set Price Display Format to decimals, not fractions";
    }
    int d = sc.BaseGraphValueFormat == 0 ? 1 : sc.BaseGraphValueFormat; // Decimal places - min = 1
    sc.ValueFormat = sc.BaseGraphValueFormat;
    int Volume, m, n, PrevBoxColor, NewBoxColor;
    OperatorEnum cond;
    double limit, HighLimit, LowLimit;
    SCFloatArray OtherArray;
    // Input vars
    float BoxSize = sc.Input[0].GetFloat();
    float ChartMulti = sc.Input[1].GetFloat();
    sc.GraphDrawType = sc.Input[2].GetYesNo() ? GDT_CANDLESTICK:GDT_CANDLESTICK_BODY_ONLY;
    int UseDynamicBoxSize = sc.Input[3].GetYesNo();
    int ChartNum = sc.Input[4].GetInt();
    int StudyNum = sc.Input[5].GetInt();
    int SubgraphNum = sc.Input[6].GetInt();
    float StudyMulti = sc.Input[7].GetFloat();
    float RoundTo = sc.Input[8].GetFloat();

    // Initial load
    if (sc.UpdateStartIndex == 0) {
      sc.ResizeArrays(0);
      // Add 2 boxes, 1st is anchor box to start the chart, 2nd is the current box.
      sc.AddElements(2);
      sc.DateTimeOut[1] = sc.DateTimeOut[0] = sc.BaseDateTimeIn[0];
      OutOpen[1] = OutOpen[0] = (sc.RoundToTickSize(InOpen[0], ChartMulti*10))+ChartMulti; // Start chart on input multiple
      OutHigh[1] = OutHigh[0] = OutOpen[0];
      OutLow[1] = OutLow[0] = OutOpen[0];
      OutClose[1] = OutClose[0] = OutOpen[0];
    }

    o = sc.OutArraySize - 1;
    // Get array from other chart if using dynamic box sizing
    if (UseDynamicBoxSize) {
      sc.GetStudyArrayFromChart(ChartNum, StudyNum, SubgraphNum, OtherArray);
      if (OtherArray.GetArraySize() == 0)  {
        throw "Error accessing ATR study on other chart, check inputs and retry";
      }
    }
    // Draw the renko chart
    for (i = sc.UpdateStartIndex; i < sc.ArraySize; i++)
    {
      PrevBoxColor = OutClose[o-1] >= OutOpen[o-1] ? GREEN_BOX:RED_BOX;

      if (UseDynamicBoxSize) {
        OtherIndex = sc.GetNearestMatchForDateTimeIndex(ChartNum, i);
        if (OtherIndex == 0) {
          throw "Other chart start date/time must be before current chart start";
        }
        BoxSize = OtherArray[OtherIndex]*StudyMulti;
        BoxSize = sc.RoundToTickSize(BoxSize, RoundTo);
        if (BoxSize <= 0.0) {
          throw "Invalid box size detected, check other chart settings and retry ";
        }
      }

      // Update current box with input bar data
      sc.DateTimeOut[o] = sc.BaseDateTimeIn[i];
      OutOpen[o] = InClose[i];
      OutClose[o] = InClose[i];
      OutColor[o] = 0;
      OutHigh[o] = InHigh[i] > OutHigh[o] ? InHigh[i] : OutHigh[o];
      if (OutLow[o] <= 0.0 || InLow[i] < OutLow[o]) {
        OutLow[o] = InLow[i];
      }
      if (InClose[i] > OutClose[o-1] && InClose[i] > OutOpen[o-1]) {
        OutOpen[o] = PrevBoxColor==GREEN_BOX ? OutClose[o-1] : OutOpen[o-1];
        OutColor[o] = GREEN_BOX;
      }
      else if (InClose[i] < OutClose[o-1] && InClose[i] < OutOpen[o-1]) {
        OutOpen[o] = PrevBoxColor==RED_BOX ? OutClose[o-1] : OutOpen[o-1];
        OutColor[o] = RED_BOX;
      }
      OutVolume[o] += InVolume[i];
      OutBoxSize[o] = BoxSize;
      OutRenkoClose[o] = InClose[i];
      OutOCR[o] = (OutOpen[o]+OutClose[o]+OutRenkoClose[o])/3.0f;
      OutOC[o] = (OutOpen[o]+OutClose[o])/2.0f;
      OutHL[o] = (OutHigh[o]+OutLow[o])/2.0f;
      OutHLC[o] = (OutHigh[o]+OutLow[o]+OutClose[o])/3.0f;
      OutOHLC[o] = (OutOpen[o]+OutHigh[o]+OutLow[o]+OutClose[o])/4.0f;
      OutColorCount[o] = OutColor[o-1]==OutColor[o] ? OutColorCount[o-1]+1.0f:1.0f;

      // If the input bar has closed check if new renko box(es) can be added
      if (i < sc.ArraySize-1) {
        if (PrevBoxColor == GREEN_BOX) {
          HighLimit = OutClose[o-1] + BoxSize;
          LowLimit = OutOpen[o-1] - BoxSize;
        }
        else {
          HighLimit = OutOpen[o-1] + BoxSize;
          LowLimit = OutClose[o-1] - BoxSize;
        }
        NewBoxColor = 0;
        if (sc.FormattedEvaluate((double)InClose[i],d,GREATER_EQUAL_OPERATOR,HighLimit,d)) {
          NewBoxColor = GREEN_BOX;
          cond = GREATER_EQUAL_OPERATOR;
          limit = HighLimit;
        }
        else if (sc.FormattedEvaluate((double)InClose[i],d,LESS_EQUAL_OPERATOR,LowLimit,d)) {
          NewBoxColor = RED_BOX;
          cond = LESS_EQUAL_OPERATOR;
          limit = LowLimit;
        }
        if (NewBoxColor != 0) {
          n = 0; // init box count
          do {                // keep adding boxes until limit reached
            if (NewBoxColor == GREEN_BOX) {
              OutClose[o+n] = (float)fround(OutOpen[o+n]+BoxSize, d);
              limit += BoxSize;
            }
            else {
              OutClose[o+n] = (float)fround(OutOpen[o+n]-BoxSize, d);
              limit -= BoxSize;
            }
            sc.DateTimeOut[o+n] = sc.DateTimeOut[o];
            OutHigh[o+n] = OutHigh[o];
            OutLow[o+n] = OutLow[o];
            OutBoxSize[o+n] = BoxSize;
            OutRenkoClose[o+n] = InClose[i];
            OutOCR[o+n] = (OutOpen[o+n]+OutClose[o+n]+OutRenkoClose[o+n])/3.0f;
            OutOC[o+n] = (OutOpen[o+n]+OutClose[o+n])/2.0f;
            OutHL[o+n] = (OutHigh[o+n]+OutLow[o+n])/2.0f;
            OutHLC[o+n] = (OutHigh[o+n]+OutLow[o+n]+OutClose[o+n])/3.0f;
            OutOHLC[o+n] = (OutOpen[o+n]+OutHigh[o+n]+OutLow[o+n]+OutClose[o+n])/4.0f;
            OutColor[o+n] = (float)NewBoxColor;
            OutColorCount[o+n] = OutColor[(o+n)-1]==OutColor[o+n] ? OutColorCount[(o+n)-1]+1.0f:1.0f;
            sc.AddElements(1);
            OutOpen[(o+n)+1] = OutClose[o+n]; // Set next open, on last iter this is open of new current box
            n++; // incr box count
          } while (sc.FormattedEvaluate((double)InClose[i],d, cond, limit,d));

          Volume = int(OutVolume[o]/n);
          for (m = 0; m < n; m++) {
            OutVolume[o+m] = (float)Volume;
          }
        }
        // All done adding boxes, now set initial values for the new current box
        o = sc.OutArraySize - 1;
        OutClose[o] = OutOpen[o];
        sc.DateTimeOut[o] = sc.BaseDateTimeIn[i]+sc.SecondsPerBar;
      }
    }  
    return;
  }
  catch (char *ErrMsg){
    sc.AddMessageToLog(ErrMsg, 1);
  }
}