Support Board
Date/Time: Thu, 03 Jul 2025 18:22:06 +0000
Jma custom study for Sierra Chart
View Count: 110
[2025-06-15 17:21:03] |
User520975 - Posts: 6 |
Could you add this to your custom studies? #include "sierrachart.h" SCDLLName("Jurik Moving Average (JMA)") SCStudyInterfaceRef g_ChartInterface; // Global reference to access chart data SCFloatArrayRef JMA = sc.Subgraph[0]; // Main JMA line SCFloatArrayRef UpperBand = sc.Subgraph[1]; // Upper volatility band SCFloatArrayRef LowerBand = sc.Subgraph[2]; // Lower volatility band SCFloatArrayRef VoltyArray = sc.PersistVars->Floats[0]; // Persistent array for volatility (size 11) SCFloatArrayRef VSum = sc.PersistVars->Floats[11]; // Persistent vSum SCFloatArrayRef AvgVolty = sc.PersistVars->Floats[12]; // Persistent avgVolty SCFloatArrayRef Det0 = sc.PersistVars->Floats[13]; // Persistent det0 SCFloatArrayRef Det1 = sc.PersistVars->Floats[14]; // Persistent det1 SCFloatArrayRef MA1 = sc.PersistVars->Floats[15]; // Persistent ma1 SCFloatArrayRef PrevJMA = sc.PersistVars->Floats[16]; // Persistent previous JMA SCInputRef Period = sc.Input[0]; SCInputRef Phase = sc.Input[1]; SCInputRef Factor = sc.Input[2]; SCInputRef Source = sc.Input[3]; SCSubgraphRef JMA_Subgraph = sc.Subgraph[0]; SCSubgraphRef UpperBand_Subgraph = sc.Subgraph[1]; SCSubgraphRef LowerBand_Subgraph = sc.Subgraph[2]; void InitializeVoltyArray(SCStudyInterfaceRef sc, int index) { for (int i = 0; i < 11; i++) VoltyArray[index * 11 + i] = 0.0f; } SCSFExport scsf_JurikMovingAverage(SCStudyInterfaceRef sc) { g_ChartInterface = sc; // Store chart interface for global access if (sc.SetDefaults) { sc.GraphName = "Jurik Moving Average (JMA)"; sc.GraphRegion = 0; sc.AutoLoop = 1; // Subgraphs JMA_Subgraph.Name = "JMA"; JMA_Subgraph.DrawStyle = DRAWSTYLE_LINE; JMA_Subgraph.PrimaryColor = RGB(255, 255, 0); // Yellow JMA_Subgraph.LineWidth = 2; UpperBand_Subgraph.Name = "Jurik Upper Band"; UpperBand_Subgraph.DrawStyle = DRAWSTYLE_LINE; UpperBand_Subgraph.PrimaryColor = RGB(128, 128, 128); // Gray UpperBand_Subgraph.LineWidth = 1; LowerBand_Subgraph.Name = "Jurik Lower Band"; LowerBand_Subgraph.DrawStyle = DRAWSTYLE_LINE; LowerBand_Subgraph.PrimaryColor = RGB(128, 128, 128); // Gray LowerBand_Subgraph.LineWidth = 1; // Inputs Period.Name = "Period"; Period.SetInt(14); Period.SetIntLimits(1, MAX_STUDY_LENGTH); Phase.Name = "Phase"; Phase.SetInt(0); Phase.SetIntLimits(-100, 100); Factor.Name = "Power"; Factor.SetFloat(0.45f); Factor.SetFloatLimits(0.1f, 1.0f); Source.Name = "Source"; Source.SetInputDataIndex(SC_LAST); // Allocate persistent storage for VoltyArray (11 elements per bar) sc.PersistVars->AllocateFloatArray(17); // 11 for VoltyArray, 1 each for vSum, avgVolty, det0, det1, ma1, prevJMA sc.AddFillAreaToGraph(UpperBand_Subgraph, LowerBand_Subgraph, RGB(128, 128, 128), 70, "Jurik Volatility Zone"); return; } // Get input values int period = Period.GetInt(); float phase = Phase.GetInt(); float factor = Factor.GetFloat(); SCFloatArray source = sc.BaseData[Source.GetInputDataIndex()]; // Pre-calculate constants float phase_value = min(max((phase * 0.01f) + 1.5f, 0.5f), 2.5f); float beta = factor * (period - 1) / ((factor * (period - 1)) + 2); float len1 = max((log(sqrt(0.5f * (period - 1))) / log(2.0f)) + 2.0f, 0.0f); float pow1 = max(len1 - 2.0f, 0.5f); float len2 = sqrt(0.5f * (period - 1)) * len1; float pow1Reciprocal = 1.0f / pow1; float avgVoltyAlpha = 2.0f / (max(4.0f * period, 65) + 1.0f); float div = 1.0f / (10.0f + 10.0f * (min(max(period - 10, 0), 100) / 100.0f)); int index = sc.Index; // Initialize persistent variables at the first bar if (index == 0) { UpperBand[index] = source[index]; LowerBand[index] = source[index]; MA1[index] = source[index]; JMA[index] = source[index]; VSum[index] = 0.0f; Det0[index] = 0.0f; Det1[index] = 0.0f; AvgVolty[index] = 0.0f; PrevJMA[index] = source[index]; InitializeVoltyArray(sc, index); } else { // Copy previous values UpperBand[index] = UpperBand[index - 1]; LowerBand[index] = LowerBand[index - 1]; MA1[index] = MA1[index - 1]; JMA[index] = JMA[index - 1]; VSum[index] = VSum[index - 1]; Det0[index] = Det0[index - 1]; Det1[index] = Det1[index - 1]; AvgVolty[index] = AvgVolty[index - 1]; PrevJMA[index] = JMA[index - 1]; // Copy VoltyArray from previous bar for (int i = 0; i < 11; i++) VoltyArray[index * 11 + i] = VoltyArray[(index - 1) * 11 + i]; } // Calculate volatility float del1 = source[index] - UpperBand[index]; float del2 = source[index] - LowerBand[index]; float volty = (fabs(del1) == fabs(del2)) ? 0.0f : max(fabs(del1), fabs(del2)); // Update VoltyArray (circular buffer) for (int i = 10; i > 0; i--) VoltyArray[index * 11 + i] = VoltyArray[index * 11 + (i - 1)]; VoltyArray[index * 11 + 0] = volty; // Calculate vSum VSum[index] = VSum[index] + (volty - VoltyArray[index * 11 + 10]) * div; // Calculate avgVolty if (index == 0) AvgVolty[index] = VSum[index]; else AvgVolty[index] = AvgVolty[index - 1] + avgVoltyAlpha * (VSum[index] - AvgVolty[index - 1]); // Calculate relative volatility float rvolty = min(max(AvgVolty[index] > 0 ? volty / AvgVolty[index] : 1.0f, 1.0f), pow(len1, pow1Reciprocal)); // Calculate adaptive parameters float pow2 = pow(rvolty, pow1); float Kv = pow(len2 / (len2 + 1), sqrt(pow2)); // Update volatility bands UpperBand[index] = (del1 > 0) ? source[index] : source[index] - Kv * del1; LowerBand[index] = (del2 < 0) ? source[index] : source[index] - Kv * del2; // Calculate dynamic factor alpha float alpha = pow(beta, pow2); float alphaSquared = alpha * alpha; float oneMinusAlpha = 1.0f - alpha; float oneMinusAlphaSquared = oneMinusAlpha * oneMinusAlpha; // 1st stage - preliminary smoothing by adaptive EMA MA1[index] = source[index] + (alpha * (MA1[index - 1] - source[index])); // 2nd stage - preliminary smoothing by Kalman filter Det0[index] = (source[index] - MA1[index]) * (1 - beta) + beta * Det0[index - 1]; float ma2 = MA1[index] + (phase_value * Det0[index]); // 3rd stage - final smoothing by unique Jurik adaptive filter Det1[index] = ((ma2 - PrevJMA[index]) * oneMinusAlphaSquared) + (alphaSquared * Det1[index - 1]); JMA[index] = PrevJMA[index] + Det1[index]; // Update PrevJMA for next iteration PrevJMA[index] = JMA[index]; } |
[2025-06-17 19:12:48] |
Sierra_Chart Engineering - Posts: 20064 |
Yes we will do that.
Sierra Chart Support - Engineering Level Your definitive source for support. Other responses are from users. Try to keep your questions brief and to the point. Be aware of support policy: https://www.sierrachart.com/index.php?l=PostingInformation.php#GeneralInformation For the most reliable, advanced, and zero cost futures order routing, use the Teton service: Sierra Chart Teton Futures Order Routing |
[2025-06-17 19:58:16] |
Sierra_Chart Engineering - Posts: 20064 |
We had a look at this, and we cannot include this study because it is using global variables. There must be no global variables at all. All variables must be within the study function itself. Example: SCStudyInterfaceRef g_ChartInterface; Sierra Chart Support - Engineering Level Your definitive source for support. Other responses are from users. Try to keep your questions brief and to the point. Be aware of support policy: https://www.sierrachart.com/index.php?l=PostingInformation.php#GeneralInformation For the most reliable, advanced, and zero cost futures order routing, use the Teton service: Sierra Chart Teton Futures Order Routing |
To post a message in this thread, you need to log in with your Sierra Chart account: