Support Board
Date/Time: Wed, 08 Oct 2025 08:09:27 +0000
Post From: code help
[2025-10-08 01:45:54] |
User688525 - Posts: 327 |
See if this works for you: #include "sierrachart.h" SCDLLName("Enhanced Signal-to-Noise Ratio") SCSFExport scsf_EnhancedSNR(SCStudyInterfaceRef sc) { // Input references SCInputRef Alpha = sc.Input[0]; SCInputRef EmaPeriod = sc.Input[1]; SCInputRef SmaPeriod = sc.Input[2]; SCInputRef Level1 = sc.Input[3]; SCInputRef Level2 = sc.Input[4]; // Subgraph references SCSubgraphRef SNR = sc.Subgraph[0]; SCSubgraphRef SMA = sc.Subgraph[1]; SCSubgraphRef EMA = sc.Subgraph[2]; // Internal arrays SCFloatArrayRef Q3 = sc.Subgraph[3].Arrays[0]; SCFloatArrayRef Noise = sc.Subgraph[3].Arrays[1]; SCFloatArrayRef Smooth = sc.Subgraph[3].Arrays[2]; SCFloatArrayRef Detrender = sc.Subgraph[3].Arrays[3]; SCFloatArrayRef I1 = sc.Subgraph[3].Arrays[4]; SCFloatArrayRef Q1 = sc.Subgraph[3].Arrays[5]; SCFloatArrayRef jI = sc.Subgraph[3].Arrays[6]; SCFloatArrayRef jQ = sc.Subgraph[3].Arrays[7]; SCFloatArrayRef I2 = sc.Subgraph[4].Arrays[0]; SCFloatArrayRef Q2 = sc.Subgraph[4].Arrays[1]; SCFloatArrayRef Re = sc.Subgraph[4].Arrays[2]; SCFloatArrayRef Im = sc.Subgraph[4].Arrays[3]; SCFloatArrayRef Per = sc.Subgraph[4].Arrays[4]; SCFloatArrayRef SmoothPeriod = sc.Subgraph[4].Arrays[5]; SCFloatArrayRef Price = sc.Subgraph[4].Arrays[6]; if (sc.SetDefaults) { sc.GraphName = "Enhanced Signal-to-Noise Ratio"; sc.StudyDescription = "Enhanced SNR with Hilbert Transform and adaptive period detection"; sc.AutoLoop = 0; sc.GraphRegion = 1; // Input defaults Alpha.Name = "Alpha (Smoothing)"; Alpha.SetFloat(0.33f); Alpha.SetFloatLimits(0.01f, 1.0f); EmaPeriod.Name = "EMA Period"; EmaPeriod.SetFloat(3.0f); EmaPeriod.SetFloatLimits(1.0f, 100.0f); SmaPeriod.Name = "SMA Period"; SmaPeriod.SetInt(12); SmaPeriod.SetIntLimits(1, 200); Level1.Name = "Level 1"; Level1.SetFloat(6.0f); Level2.Name = "Level 2"; Level2.SetFloat(0.0f); // Subgraph settings SNR.Name = "SNR"; SNR.DrawStyle = DRAWSTYLE_LINE; SNR.PrimaryColor = RGB(128, 128, 128); // Dark Gray SNR.LineWidth = 1; SNR.DrawZeros = false; SMA.Name = "SMA"; SMA.DrawStyle = DRAWSTYLE_DASH; SMA.PrimaryColor = RGB(255, 215, 0); // Gold SMA.LineWidth = 1; SMA.DrawZeros = false; EMA.Name = "EMA"; EMA.DrawStyle = DRAWSTYLE_LINE; EMA.PrimaryColor = RGB(30, 144, 255); // Dodger Blue EMA.LineWidth = 2; EMA.DrawZeros = false; return; } // Section 2 - Do data processing here // Calculation int MinBar = 7; int StartIndex = sc.UpdateStartIndex; if (StartIndex < MinBar) StartIndex = MinBar; for (int i = StartIndex; i < sc.ArraySize; i++) { // Calculate median price Price[i] = (sc.High[i] + sc.Low[i]) / 2.0f; // Hilbert Transform calculation if (i >= 6) { // Smooth price Smooth[i] = (4.0f * Price[i] + 3.0f * Price[i-1] + 2.0f * Price[i-2] + Price[i-3]) / 10.0f; if (i >= 6 && Per[i-1] > 0) { // Detrender Detrender[i] = (0.0962f * Smooth[i] + 0.5769f * Smooth[i-2] - 0.5769f * Smooth[i-4] - 0.0962f * Smooth[i-6]) * (0.075f * Per[i-1] + 0.54f); // InPhase and Quadrature components Q1[i] = (0.0962f * Detrender[i] + 0.5769f * Detrender[i-2] - 0.5769f * Detrender[i-4] - 0.0962f * Detrender[i-6]) * (0.075f * Per[i-1] + 0.54f); I1[i] = Detrender[i-3]; // Advance phase by 90 degrees jI[i] = (0.0962f * I1[i] + 0.5769f * I1[i-2] - 0.5769f * I1[i-4] - 0.0962f * I1[i-6]) * (0.075f * Per[i-1] + 0.54f); jQ[i] = (0.0962f * Q1[i] + 0.5769f * Q1[i-2] - 0.5769f * Q1[i-4] - 0.0962f * Q1[i-6]) * (0.075f * Per[i-1] + 0.54f); // Phasor Addition I2[i] = I1[i] - jQ[i]; Q2[i] = Q1[i] + jI[i]; // Smooth I and Q components I2[i] = 0.2f * I2[i] + 0.8f * I2[i-1]; Q2[i] = 0.2f * Q2[i] + 0.8f * Q2[i-1]; // Homodyne Discriminator Re[i] = I2[i] * I2[i-1] + Q2[i] * Q2[i-1]; Im[i] = I2[i] * Q2[i-1] - Q2[i] * I2[i-1]; Re[i] = 0.2f * Re[i] + 0.8f * Re[i-1]; Im[i] = 0.2f * Im[i] + 0.8f * Im[i-1]; // Calculate period if (Im[i] != 0 && Re[i] != 0) Per[i] = 2.0f * (float)M_PI / atan(Im[i] / Re[i]); else Per[i] = Per[i-1]; // Limit period changes if (Per[i] > 1.5f * Per[i-1]) Per[i] = 1.5f * Per[i-1]; if (Per[i] < 0.67f * Per[i-1]) Per[i] = 0.67f * Per[i-1]; if (Per[i] < 6) Per[i] = 6; if (Per[i] > 50) Per[i] = 50; Per[i] = 0.2f * Per[i] + 0.8f * Per[i-1]; SmoothPeriod[i] = Alpha.GetFloat() * Per[i] + (1.0f - Alpha.GetFloat()) * SmoothPeriod[i-1]; } else { Per[i] = 10.0f; SmoothPeriod[i] = 10.0f; } // Calculate Q3 Q3[i] = 0.5f * (Smooth[i] - Smooth[i-2]) * (0.1759f * SmoothPeriod[i] + 0.4607f); // Calculate I3 int sp = (int)ceil(SmoothPeriod[i] / 2.0f); if (sp == 0) sp = 1; if (sp > i) sp = i; float i3 = 0.0f; for (int j = 0; j < sp; j++) { i3 += Q3[i-j]; } i3 = (1.57f * i3) / (float)sp; // Calculate signal and noise float signal = pow(i3, 2) + pow(Q3[i], 2); Noise[i] = 0.1f * pow((sc.High[i] - sc.Low[i]), 2) * 0.25f + 0.9f * Noise[i-1]; // Calculate SNR if (Noise[i] != 0.0f && signal != 0.0f) { SNR[i] = Alpha.GetFloat() * (10.0f * log10(signal / Noise[i])) + (1.0f - Alpha.GetFloat()) * SNR[i-1]; } else { SNR[i] = SNR[i-1]; } } // Calculate SMA if (i >= SmaPeriod.GetInt() - 1) { float sum = 0.0f; for (int j = 0; j < SmaPeriod.GetInt(); j++) { sum += SNR[i-j]; } SMA[i] = sum / (float)SmaPeriod.GetInt(); } // Calculate EMA if (i == MinBar) { EMA[i] = SNR[i]; } else { float emaAlpha = 2.0f / (1.0f + EmaPeriod.GetFloat()); EMA[i] = emaAlpha * SNR[i] + (1.0f - emaAlpha) * EMA[i-1]; } } // Set reference lines sc.Subgraph[0].LineLabel = LL_DISPLAY_VALUE | LL_VALUE_ALIGN_VALUES_SCALE; sc.Subgraph[1].LineLabel = LL_DISPLAY_VALUE | LL_VALUE_ALIGN_VALUES_SCALE; sc.Subgraph[2].LineLabel = LL_DISPLAY_VALUE | LL_VALUE_ALIGN_VALUES_SCALE; } |