mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-05 12:37:43 +00:00
146 lines
4.7 KiB
C#
146 lines
4.7 KiB
C#
//not working yet
|
|
//TODO consistency test
|
|
|
|
using QuanTAlib;
|
|
|
|
public class Htit : AbstractBase
|
|
{
|
|
private readonly CircularBuffer _priceBuffer = new(7);
|
|
private readonly CircularBuffer _spBuffer = new(7);
|
|
private readonly CircularBuffer _dtBuffer = new(7);
|
|
private readonly CircularBuffer _i1Buffer = new(7);
|
|
private readonly CircularBuffer _q1Buffer = new(7);
|
|
private readonly CircularBuffer _i2Buffer = new(2);
|
|
private readonly CircularBuffer _q2Buffer = new(2);
|
|
private readonly CircularBuffer _reBuffer = new(2);
|
|
private readonly CircularBuffer _imBuffer = new(2);
|
|
private readonly CircularBuffer _pdBuffer = new(2);
|
|
private readonly CircularBuffer _sdBuffer = new(2);
|
|
private readonly CircularBuffer _itBuffer = new(4);
|
|
|
|
private double _lastPd = 0;
|
|
private double _p_lastPd = 0;
|
|
|
|
public Htit() : base()
|
|
{
|
|
Name = "Htit";
|
|
WarmupPeriod = 12;
|
|
}
|
|
|
|
public Htit(object source) : this()
|
|
{
|
|
var pubEvent = source.GetType().GetEvent("Pub");
|
|
pubEvent?.AddEventHandler(source, new ValueSignal(Sub));
|
|
}
|
|
|
|
protected override void ManageState(bool isNew)
|
|
{
|
|
if (isNew)
|
|
{
|
|
_p_lastPd = _lastPd;
|
|
_index++;
|
|
}
|
|
else
|
|
{
|
|
_lastPd = _p_lastPd;
|
|
}
|
|
}
|
|
protected override double Calculation()
|
|
{
|
|
ManageState(Input.IsNew);
|
|
|
|
double pr = Input.Value;
|
|
_priceBuffer.Add(pr, Input.IsNew);
|
|
|
|
if (_index <= 5)
|
|
{
|
|
_spBuffer.Add(0, Input.IsNew);
|
|
_dtBuffer.Add(0, Input.IsNew);
|
|
_i1Buffer.Add(0, Input.IsNew);
|
|
_q1Buffer.Add(0, Input.IsNew);
|
|
_i2Buffer.Add(0, Input.IsNew);
|
|
_q2Buffer.Add(0, Input.IsNew);
|
|
_reBuffer.Add(0, Input.IsNew);
|
|
_imBuffer.Add(0, Input.IsNew);
|
|
_pdBuffer.Add(0, Input.IsNew);
|
|
_sdBuffer.Add(0, Input.IsNew);
|
|
_itBuffer.Add(pr, Input.IsNew);
|
|
return pr;
|
|
}
|
|
|
|
double adj = (0.075 * _lastPd) + 0.54;
|
|
|
|
// Smooth and detrender
|
|
double sp = ((4 * _priceBuffer[0]) + (3 * _priceBuffer[1]) + (2 * _priceBuffer[2]) + _priceBuffer[3]) / 10;
|
|
_spBuffer.Add(sp, Input.IsNew);
|
|
|
|
double dt = ((0.0962 * _spBuffer[0]) + (0.5769 * _spBuffer[2]) - (0.5769 * _spBuffer[4]) - (0.0962 * _spBuffer[6])) * adj;
|
|
_dtBuffer.Add(dt, Input.IsNew);
|
|
|
|
// In-phase and quadrature
|
|
double q1 = ((0.0962 * _dtBuffer[0]) + (0.5769 * _dtBuffer[2]) - (0.5769 * _dtBuffer[4]) - (0.0962 * _dtBuffer[6])) * adj;
|
|
_q1Buffer.Add(q1, Input.IsNew);
|
|
|
|
double i1 = _dtBuffer[3];
|
|
_i1Buffer.Add(i1, Input.IsNew);
|
|
|
|
// Advance the phases by 90 degrees
|
|
double jI = ((0.0962 * _i1Buffer[0]) + (0.5769 * _i1Buffer[2]) - (0.5769 * _i1Buffer[4]) - (0.0962 * _i1Buffer[6])) * adj;
|
|
double jQ = ((0.0962 * _q1Buffer[0]) + (0.5769 * _q1Buffer[2]) - (0.5769 * _q1Buffer[4]) - (0.0962 * _q1Buffer[6])) * adj;
|
|
|
|
// Phasor addition for 3-bar averaging
|
|
double i2 = i1 - jQ;
|
|
double q2 = q1 + jI;
|
|
|
|
i2 = (0.2 * i2) + (0.8 * _i2Buffer[0]);
|
|
q2 = (0.2 * q2) + (0.8 * _q2Buffer[0]);
|
|
|
|
_i2Buffer.Add(i2, Input.IsNew);
|
|
_q2Buffer.Add(q2, Input.IsNew);
|
|
|
|
// Homodyne discriminator
|
|
double re = (i2 * _i2Buffer[1]) + (q2 * _q2Buffer[1]);
|
|
double im = (i2 * _q2Buffer[1]) - (q2 * _i2Buffer[1]);
|
|
|
|
re = (0.2 * re) + (0.8 * _reBuffer[0]);
|
|
im = (0.2 * im) + (0.8 * _imBuffer[0]);
|
|
|
|
_reBuffer.Add(re, Input.IsNew);
|
|
_imBuffer.Add(im, Input.IsNew);
|
|
|
|
// Calculate period
|
|
double pd = (im != 0 && re != 0) ? 2 * Math.PI / Math.Atan(im / re) : 0;
|
|
|
|
// Adjust period to thresholds
|
|
pd = (pd > 1.5 * _lastPd) ? 1.5 * _lastPd : pd;
|
|
pd = (pd < 0.67 * _lastPd) ? 0.67 * _lastPd : pd;
|
|
pd = (pd < 6) ? 6 : pd;
|
|
pd = (pd > 50) ? 50 : pd;
|
|
|
|
// Smooth the period
|
|
pd = (0.2 * pd) + (0.8 * _lastPd);
|
|
_pdBuffer.Add(pd, Input.IsNew);
|
|
|
|
double sd = (0.33 * pd) + (0.67 * _sdBuffer[0]);
|
|
_sdBuffer.Add(sd, Input.IsNew);
|
|
|
|
// Smooth dominant cycle period
|
|
int dcPeriods = (int)(sd + 0.5);
|
|
double sumPr = _priceBuffer.GetSpan().Slice(0, Math.Min(dcPeriods, _priceBuffer.Count)).ToArray().Sum();
|
|
double it = dcPeriods > 0 ? sumPr / dcPeriods : pr;
|
|
_itBuffer.Add(it, Input.IsNew);
|
|
|
|
_p_lastPd = _lastPd;
|
|
_lastPd = pd;
|
|
|
|
// Final indicator
|
|
if (_index >= 11) // 12th bar
|
|
{
|
|
return ((4 * _itBuffer[0]) + (3 * _itBuffer[1]) + (2 * _itBuffer[2]) + _itBuffer[3]) / 10;
|
|
}
|
|
else
|
|
{
|
|
return pr;
|
|
}
|
|
}
|
|
} |