mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-06 04:57:44 +00:00
130 lines
4.2 KiB
C#
130 lines
4.2 KiB
C#
using QuanTAlib;
|
|
//TODO consistency test
|
|
public class Jma : AbstractBase
|
|
{
|
|
public readonly int Period;
|
|
private readonly double _phase;
|
|
private readonly int _vshort, _vlong;
|
|
private CircularBuffer _values;
|
|
private CircularBuffer _voltyShort;
|
|
private CircularBuffer _vsumBuff;
|
|
private CircularBuffer _avoltyBuff;
|
|
|
|
private double _beta, _len1, _pow1;
|
|
private double _upperBand, _lowerBand, _prevMa1, _prevDet0, _prevDet1, _prevJma;
|
|
private double _p_UpperBand, _p_LowerBand, _p_prevMa1, _p_prevDet0, _p_prevDet1, _p_prevJma;
|
|
|
|
public Jma(int period, double phase = 0, int vshort = 10) : base()
|
|
{
|
|
if (period < 1)
|
|
{
|
|
throw new ArgumentOutOfRangeException(nameof(period), "Period must be greater than or equal to 1.");
|
|
}
|
|
Period = period;
|
|
_vshort = vshort;
|
|
_vlong = 65;
|
|
_phase = Math.Clamp((phase * 0.01) + 1.5, 0.5, 2.5);
|
|
|
|
_values = new CircularBuffer(period);
|
|
_voltyShort = new CircularBuffer(vshort);
|
|
_vsumBuff = new CircularBuffer(_vlong);
|
|
_avoltyBuff = new CircularBuffer(2);
|
|
|
|
Name = "JMA";
|
|
WarmupPeriod = period * 2;
|
|
Init();
|
|
}
|
|
|
|
public override void Init()
|
|
{
|
|
_upperBand = _lowerBand = _prevMa1 = _prevDet0 = _prevDet1 = _prevJma = 0.0;
|
|
_p_UpperBand = _p_LowerBand = _p_prevMa1 = _p_prevDet0 = _p_prevDet1 = _p_prevJma = 0.0;
|
|
_beta = 0.45 * (Period - 1) / (0.45 * (Period - 1) + 2);
|
|
_len1 = Math.Max((Math.Log(Math.Sqrt(Period - 1)) / Math.Log(2.0)) + 2.0, 0);
|
|
_pow1 = Math.Max(_len1 - 2.0, 0.5);
|
|
_avoltyBuff.Clear();
|
|
_avoltyBuff.Add(0, true);
|
|
_avoltyBuff.Add(0, true);
|
|
base.Init();
|
|
}
|
|
|
|
protected override void ManageState(bool isNew)
|
|
{
|
|
if (isNew)
|
|
{
|
|
_lastValidValue = Input.Value;
|
|
_index++;
|
|
// Save current state
|
|
_p_UpperBand = _upperBand;
|
|
_p_LowerBand = _lowerBand;
|
|
_p_prevMa1 = _prevMa1;
|
|
_p_prevDet0 = _prevDet0;
|
|
_p_prevDet1 = _prevDet1;
|
|
_p_prevJma = _prevJma;
|
|
}
|
|
else
|
|
{
|
|
// Restore previous state
|
|
_upperBand = _p_UpperBand;
|
|
_lowerBand = _p_LowerBand;
|
|
_prevMa1 = _p_prevMa1;
|
|
_prevDet0 = _p_prevDet0;
|
|
_prevDet1 = _p_prevDet1;
|
|
_prevJma = _p_prevJma;
|
|
|
|
}
|
|
}
|
|
protected override double Calculation()
|
|
{
|
|
ManageState(Input.IsNew);
|
|
|
|
_values.Add(Input.Value, Input.IsNew);
|
|
|
|
if (_index == 1)
|
|
{
|
|
_prevMa1 = _prevJma = Input.Value;
|
|
return Input.Value;
|
|
}
|
|
|
|
double hprice = _values.Max();
|
|
double lprice = _values.Min();
|
|
|
|
double del1 = hprice - _upperBand;
|
|
double del2 = lprice - _lowerBand;
|
|
double volty = Math.Max(Math.Abs(del1), Math.Abs(del2));
|
|
|
|
_voltyShort.Add(volty, Input.IsNew);
|
|
double vsum = _vsumBuff.Newest() + 0.1 * (volty - _voltyShort.Oldest());
|
|
_vsumBuff.Add(vsum, Input.IsNew);
|
|
|
|
double prevAvolty = _avoltyBuff.Newest();
|
|
double avolty = prevAvolty + 2.0 / (Math.Max(4.0 * Period, 30) + 1.0) * (vsum - prevAvolty);
|
|
_avoltyBuff.Add(avolty, Input.IsNew);
|
|
|
|
double dVolty = (avolty > 0) ? volty / avolty : 0;
|
|
dVolty = Math.Min(Math.Max(dVolty, 1.0), Math.Pow(_len1, 1.0 / _pow1));
|
|
|
|
double pow2 = Math.Pow(dVolty, _pow1);
|
|
double len2 = Math.Sqrt(0.5 * (Period - 1)) * _len1;
|
|
double _Kv = Math.Pow(len2 / (len2 + 1), Math.Sqrt(pow2));
|
|
|
|
_upperBand = (del1 > 0) ? hprice : hprice - (_Kv * del1);
|
|
_lowerBand = (del2 < 0) ? lprice : lprice - (_Kv * del2);
|
|
|
|
double alpha = Math.Pow(_beta, pow2);
|
|
double ma1 = (1 - alpha) * Input.Value + alpha * _prevMa1;
|
|
_prevMa1 = ma1;
|
|
|
|
double det0 = (1 - _beta) * (Input.Value - ma1) + _beta * _prevDet0;
|
|
_prevDet0 = det0;
|
|
double ma2 = ma1 + (_phase + 1) * det0;
|
|
|
|
double det1 = ((1 - alpha) * (1 - alpha) * (ma2 - _prevJma)) + (alpha * alpha * _prevDet1);
|
|
_prevDet1 = det1;
|
|
double jma = _prevJma + det1;
|
|
_prevJma = jma;
|
|
|
|
IsHot = _index >= WarmupPeriod;
|
|
return jma;
|
|
}
|
|
} |