-
Notifications
You must be signed in to change notification settings - Fork 64
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement Least Square MA #23
Comments
This https://pythonnumericalmethods.studentorg.berkeley.edu/notebooks/chapter16.04-Least-Squares-Regression-in-Python.html could help (Least Squares Regression) QuantConnect Lean (C#) provides such an indicator How such an indicator should work when input data are not equally spaced in time? |
I have done some tests with QC (Research environment)... Here is code CLOSE_TMPL = [10.5, 9.78, 10.46, 10.51, 10.55, 10.72, 10.16, 10.25, 9.4, 9.5, 9.23, 8.5, 8.8, 8.33, 7.53, 7.61, 6.78, 8.6, 9.21, 8.95, 9.22, 9.1, 8.31, 8.37, 8.3, 7.78, 8.05, 8.1, 8.08, 7.49, 7.58, 8.17, 8.83, 8.91, 9.2, 9.76, 9.42, 9.3, 9.32, 9.04, 9.0, 9.33, 9.34, 8.49, 9.21, 10.15, 10.3, 10.59, 10.23, 10.0]
TIME_TMPL = pd.date_range("2020-01-01", freq="D", periods=len(CLOSE_TMPL))
df = pd.DataFrame({"Close": CLOSE_TMPL}, index=TIME_TMPL)
period = 5
indicator = LeastSquaresMovingAverage(period)
indicator.is_ready, indicator.current.time, indicator.current.value
indicator_is_ready = []
indicator_output_values = []
prec = 2
for row in df.iterrows():
current_time, current_value = row
current_value = Decimal(current_value["Close"]).quantize(Decimal(10)**-prec)
indicator.update(current_time, current_value)
indicator_is_ready.append(indicator.is_ready)
indicator_output_values.append(indicator.current.value)
#print(current_time, current_value, indicator.is_ready, indicator.current.value) # value = Intercept.Current.Value + Slope.Current.Value * Period
df["is_ready"] = indicator_is_ready
df["indicator_output_values"] = indicator_output_values
df and output
I can't output separately slope and intercept but only This kind of unit tests can also help (in [Test]
public void TalippCompare_with_period_2()
{
decimal[] CLOSE_TMPL = new decimal[]
{
10.5m, 9.78m, 10.46m, 10.51m, 10.55m, 10.72m, 10.16m, 10.25m, 9.4m, 9.5m,
9.23m, 8.5m, 8.8m, 8.33m, 7.53m, 7.61m, 6.78m, 8.6m, 9.21m, 8.95m,
9.22m, 9.1m, 8.31m, 8.37m, 8.3m, 7.78m, 8.05m, 8.1m, 8.08m, 7.49m,
7.58m, 8.17m, 8.83m, 8.91m, 9.2m, 9.76m, 9.42m, 9.3m, 9.32m, 9.04m,
9.0m, 9.33m, 9.34m, 8.49m, 9.21m, 10.15m, 10.3m, 10.59m, 10.23m, 10.0m
};
DateTime[] DATE_TMPL = Enumerable.Range(0, CLOSE_TMPL.Length)
.Select(i => new DateTime(2024, 7, 7).AddDays(i))
.ToArray();
decimal[] expected_slope = new decimal[]
{
0m, -0.720m, 0.680m, 0.050m, 0.040m, 0.170m, -0.560m, 0.090m, -0.85m, 0.100m,
-0.270m, -0.730m, 0.300m, -0.470m, -0.800m, 0.080m, -0.830m, 1.820m, 0.610m, -0.260m,
0.270m, -0.120m, -0.790m, 0.060m, -0.070m, -0.520m, 0.270m, 0.050m, -0.020m, -0.590m,
0.090m, 0.590m, 0.660m, 0.080m, 0.290m, 0.560m, -0.340m, -0.120m, 0.020m, -0.280m,
-0.040m, 0.330m, 0.0100m, -0.850m, 0.720m, 0.940m, 0.150m, 0.290m, -0.360m, -0.230m
};
decimal[] expected_intercept = new decimal[]
{
0.000m, 11.220m, 9.100m, 10.410m, 10.470m, 10.380m, 11.280m, 10.070m, 11.100m, 9.300m,
9.770m, 9.960m, 8.200m, 9.270m, 9.130m, 7.450m, 8.440m, 4.960m, 7.990m, 9.470m,
8.680m, 9.340m, 9.890m, 8.250m, 8.440m, 8.820m, 7.510m, 8.000m, 8.120m, 8.670m,
7.400m, 6.990m, 7.510m, 8.750m, 8.620m, 8.640m, 10.100m, 9.540m, 9.280m, 9.600m,
9.080m, 8.670m, 9.320m, 10.190m, 7.770m, 8.270m, 10.000m, 10.010m, 10.950m, 10.460m
};
var indicator = new LeastSquaresMovingAverage(2);
for (int i=0; i<CLOSE_TMPL.Length; i++)
{
indicator.Update(DATE_TMPL[i], CLOSE_TMPL[i]);
Assert.AreEqual(Math.Round((decimal)indicator.Slope.Current.Value, 4), expected_slope[i]);
Assert.AreEqual(indicator.Intercept.Current.Value, expected_intercept[i]);
Assert.AreEqual(Math.Round((decimal)indicator.Current.Value, 4), CLOSE_TMPL[i]);
}
}
[Test]
public void TalippCompare_with_period_5()
{
decimal[] CLOSE_TMPL = new decimal[]
{
10.5m, 9.78m, 10.46m, 10.51m, 10.55m, 10.72m, 10.16m, 10.25m, 9.4m, 9.5m,
9.23m, 8.5m, 8.8m, 8.33m, 7.53m, 7.61m, 6.78m, 8.6m, 9.21m, 8.95m,
9.22m, 9.1m, 8.31m, 8.37m, 8.3m, 7.78m, 8.05m, 8.1m, 8.08m, 7.49m,
7.58m, 8.17m, 8.83m, 8.91m, 9.2m, 9.76m, 9.42m, 9.3m, 9.32m, 9.04m,
9.0m, 9.33m, 9.34m, 8.49m, 9.21m, 10.15m, 10.3m, 10.59m, 10.23m, 10.0m
};
DateTime[] DATE_TMPL = Enumerable.Range(0, CLOSE_TMPL.Length)
.Select(i => new DateTime(2024, 7, 7).AddDays(i))
.ToArray();
//decimal[] expected_zeros = Enumerable.Repeat(0m, 50).ToArray();
decimal[] expected_slope = new decimal[]
{
0.000m, 0.000m, 0.000m, 0.000m, 0.083m, 0.197m, -0.039m, -0.091m, -0.277m, -0.320m,
-0.261m, -0.367m, -0.220m, -0.277m, -0.357m, -0.305m, -0.476m, -0.021m, 0.435m, 0.511m,
0.523m, 0.101m, -0.165m, -0.207m, -0.257m, -0.265m, -0.111m, -0.079m, -0.012m, -0.055m,
-0.155m, -0.036m, 0.218m, 0.409m, 0.398m, 0.355m, 0.203m, 0.100m, -0.022m, -0.154m,
-0.110m, -0.026m, 0.033m, -0.076m, -0.042m, 0.151m, 0.358m, 0.529m, 0.248m, -0.037m
};
decimal[] expected_intercept = new decimal[]
{
0.000m, 0.000m, 0.000m, 0.000m, 10.111m, 9.813m, 10.597m, 10.711m, 11.047m, 10.966m,
10.491m, 10.477m, 9.746m, 9.703m, 9.549m, 9.069m, 9.238m, 7.833m, 6.641m, 6.697m,
6.983m, 8.713m, 9.453m, 9.411m, 9.431m, 9.167m, 8.495m, 8.357m, 8.098m, 8.065m,
8.325m, 7.992m, 7.376m, 6.969m, 7.344m, 7.909m, 8.615m, 9.018m, 9.466m, 9.830m,
9.546m, 9.276m, 9.107m, 9.268m, 9.200m, 8.851m, 8.424m, 8.161m, 9.352m, 10.365m
};
decimal[] expected_pred = new decimal[]
{
10.5m, 9.78m, 10.46m, 10.51m, 10.526m, 10.798m, 10.402m, 10.256m, 9.662m, 9.366m,
9.186m, 8.642m, 8.646m, 8.318m, 7.764m, 7.544m, 6.858m, 7.728m, 8.816m, 9.252m,
9.598m, 9.218m, 8.628m, 8.376m, 8.146m, 7.842m, 7.940m, 7.962m, 8.038m, 7.790m,
7.550m, 7.812m, 8.466m, 9.014m, 9.334m, 9.684m, 9.630m, 9.518m, 9.356m, 9.060m,
8.996m, 9.146m, 9.272m, 8.888m, 8.990m, 9.606m, 10.214m, 10.806m, 10.592m, 10.180m
};
var indicator = new LeastSquaresMovingAverage(5);
for (int i = 0; i < CLOSE_TMPL.Length; i++)
{
indicator.Update(DATE_TMPL[i], CLOSE_TMPL[i]);
Assert.AreEqual(Math.Round((decimal)indicator.Slope.Current.Value, 4), expected_slope[i]);
Assert.AreEqual(indicator.Intercept.Current.Value, expected_intercept[i]);
Assert.AreEqual(Math.Round((decimal)indicator.Current.Value, 4), expected_pred[i]);
}
} |
#149 is a draft PR to showcase a possible solution using Numpy. Reference data for unit tests come from QuantConnect Lean but I'm not 100% sure that it's good enough. I think this implementation works correctly only with regularly time spaced incoming data (which is the case here) but it shouldn't behave correcly when data are irrregularly time spaced. |
I wonder if LSMA is different from Time Series Forecast (TSF) implemented in Tulip |
Thanks a lot for this! Unfortunately I cannot spend much time with the library but I am looking forward to look into this as soon as possible. |
I wonder how TSF https://tulipindicators.org/tsf is different from LSMA |
No description provided.
The text was updated successfully, but these errors were encountered: