Login Page - Create Account

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;
}