diff --git a/Source/Feeds/GBM_Feed.cs b/Source/Feeds/GBM_Feed.cs index 85a0dfbd..d54ffe9b 100644 --- a/Source/Feeds/GBM_Feed.cs +++ b/Source/Feeds/GBM_Feed.cs @@ -51,7 +51,7 @@ public class GBM_Feed : TBars } private static double GBM_value (double Seed, double Volatility, double Drift) { - Random rnd = new((int)(DateTime.UtcNow.Ticks)); + Random rnd = new(); double U1 = 1.0-rnd.NextDouble(); double U2 = 1.0-rnd.NextDouble(); double Z = Math.Sqrt(-2.0 * Math.Log(U1)) * Math.Sin(2.0 * Math.PI * U2); diff --git a/Source/QuanTAlib.csproj b/Source/QuanTAlib.csproj index f5c5c2a2..6a47408d 100644 --- a/Source/QuanTAlib.csproj +++ b/Source/QuanTAlib.csproj @@ -1,7 +1,7 @@  - 0.1.14 + 0.1.15 QuanTAlib diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index a3829bd3..2fc9db68 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -28,24 +28,17 @@ - - - - - - - - - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/Tests/Validations/Pandas_TA.cstemp b/Tests/Validations/Pandas_TA.cs similarity index 95% rename from Tests/Validations/Pandas_TA.cstemp rename to Tests/Validations/Pandas_TA.cs index 0aa769bd..641b6cb7 100644 --- a/Tests/Validations/Pandas_TA.cstemp +++ b/Tests/Validations/Pandas_TA.cs @@ -1,120 +1,124 @@ -using Xunit; -using System; -using QuanTAlib; -using Python.Runtime; -using Python.Included; - -namespace Validation; -public class PandasTA -{ - private readonly RND_Feed bars; - private readonly Random rnd = new(); - private readonly int period; - private readonly dynamic ta; - private readonly dynamic df; - - public PandasTA() - { - this.bars = new(1000); - this.period = this.rnd.Next(28) + 3; - - Installer.SetupPython().Wait(); - Installer.TryInstallPip(); - Installer.PipInstallModule("numpy"); - Installer.PipInstallModule("pandas"); - Installer.PipInstallModule("pandas-ta"); - PythonEngine.Initialize(); - this.ta = Py.Import("pandas_ta"); - this.df = this.ta.DataFrame(this.bars.Close.v); - } - - ~PandasTA() - { - PythonEngine.Shutdown(); - } - - [Fact] - void SMA() - { - SMA_Series QL = new(this.bars.Close, this.period, false); - var pta = this.ta.sma(close: this.df[0], length: this.period); - - Assert.Equal(System.Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); - } - -/* - [Fact] - void EMA() - { - EMA_Series QL = new(this.bars.Close, this.period, false); - var pta = this.ta.ema(close: this.df[0], length: this.period); - - Assert.Equal(System.Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); - } - - [Fact] - void TEMA() - { - TEMA_Series QL = new(this.bars.Close, this.period, false); - var pta = this.ta.tema(close: this.df[0], length: this.period); - - Assert.Equal(System.Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); - } - - [Fact] - void ENTP() - { - ENTP_Series QL = new(this.bars.Close, this.period, useNaN:false); - var pta = this.ta.entropy(close: this.df[0], length: this.period); - - Assert.Equal(System.Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); - } - - - [Fact] - void WMA() - { - WMA_Series QL = new(this.bars.Close, this.period, false); - var pta = this.ta.wma(close: this.df[0], length: this.period); - - Assert.Equal(System.Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); - } - - [Fact] - void DEMA() - { - DEMA_Series QL = new(this.bars.Close, this.period, false); - var pta = this.ta.dema(close: this.df[0], length: this.period); - - Assert.Equal(System.Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); - } - - [Fact] - void BIAS() - { - BIAS_Series QL = new(this.bars.Close, this.period, false); - var pta = this.ta.bias(close: this.df[0], length: this.period); - - Assert.Equal(System.Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); - } - - [Fact] - void KURT() - { - KURT_Series QL = new(this.bars.Close, this.period, useNaN: false); - var pta = this.ta.kurtosis(close: this.df[0], length: this.period); - - Assert.Equal(System.Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4)); - } - - [Fact] - void MAD() - { - MAD_Series QL = new(this.bars.Close, this.period, useNaN: false); - var pta = this.ta.mad(close: this.df[0], length: this.period); - - Assert.Equal(System.Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); - } -*/ - -} \ No newline at end of file +/* + +using Xunit; +using System; +using QuanTAlib; +using Python.Runtime; +using Python.Included; + +namespace Validation; +public class PandasTA +{ + private readonly RND_Feed bars; + private readonly Random rnd = new(); + private readonly int period; + private readonly dynamic ta; + private readonly dynamic df; + + public PandasTA() + { + this.bars = new(1000); + this.period = this.rnd.Next(28) + 3; + + Installer.SetupPython().Wait(); + Installer.TryInstallPip(); + Installer.PipInstallModule("numpy"); + Installer.PipInstallModule("pandas"); + Installer.PipInstallModule("pandas-ta"); + PythonEngine.Initialize(); + this.ta = Py.Import("pandas_ta"); + this.df = this.ta.DataFrame(this.bars.Close.v); + } + + ~PandasTA() + { + PythonEngine.Shutdown(); + } + + [Fact] + void SMA() + { + SMA_Series QL = new(this.bars.Close, this.period, false); + var pta = this.ta.sma(close: this.df[0], length: this.period); + + Assert.Equal(System.Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); + } + + + [Fact] + void EMA() + { + EMA_Series QL = new(this.bars.Close, this.period, false); + var pta = this.ta.ema(close: this.df[0], length: this.period); + + Assert.Equal(System.Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); + } + + + [Fact] + void TEMA() + { + TEMA_Series QL = new(this.bars.Close, this.period, false); + var pta = this.ta.tema(close: this.df[0], length: this.period); + + Assert.Equal(System.Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); + } + + [Fact] + void ENTP() + { + ENTP_Series QL = new(this.bars.Close, this.period, useNaN:false); + var pta = this.ta.entropy(close: this.df[0], length: this.period); + + Assert.Equal(System.Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); + } + + + [Fact] + void WMA() + { + WMA_Series QL = new(this.bars.Close, this.period, false); + var pta = this.ta.wma(close: this.df[0], length: this.period); + + Assert.Equal(System.Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); + } + + [Fact] + void DEMA() + { + DEMA_Series QL = new(this.bars.Close, this.period, false); + var pta = this.ta.dema(close: this.df[0], length: this.period); + + Assert.Equal(System.Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); + } + + [Fact] + void BIAS() + { + BIAS_Series QL = new(this.bars.Close, this.period, false); + var pta = this.ta.bias(close: this.df[0], length: this.period); + + Assert.Equal(System.Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); + } + + [Fact] + void KURT() + { + KURT_Series QL = new(this.bars.Close, this.period, useNaN: false); + var pta = this.ta.kurtosis(close: this.df[0], length: this.period); + + Assert.Equal(System.Math.Round((double)pta.tail(1), 4), Math.Round(QL.Last().v, 4)); + } + + [Fact] + void MAD() + { + MAD_Series QL = new(this.bars.Close, this.period, useNaN: false); + var pta = this.ta.mad(close: this.df[0], length: this.period); + + Assert.Equal(System.Math.Round((double)pta.tail(1), 7), Math.Round(QL.Last().v, 7)); + } + +} + +*/ \ No newline at end of file diff --git a/Tests/Validations/Skender_Stock.cs b/Tests/Validations/Skender_Stock.cs index c45517bf..319ed5ca 100644 --- a/Tests/Validations/Skender_Stock.cs +++ b/Tests/Validations/Skender_Stock.cs @@ -7,7 +7,7 @@ using Xunit; namespace Validation; public class Skender_Stock { - private readonly RND_Feed bars; + private readonly GBM_Feed bars; private readonly Random rnd = new(); private readonly int period; private readonly IEnumerable quotes; @@ -32,7 +32,7 @@ public class Skender_Stock public void SMA() { SMA_Series QL = new(this.bars.Close, this.period, false); - var SK = this.quotes.GetSma(this.period, CandlePart.Close); + var SK = this.quotes.GetSma(this.period); Assert.Equal(Math.Round((double)SK.Last().Sma!, 8), Math.Round(QL.Last().v, 8)); } @@ -41,7 +41,7 @@ public class Skender_Stock public void EMA() { EMA_Series QL = new(this.bars.Close, this.period, false); - var SK = this.quotes.GetEma(this.period, CandlePart.Close); + var SK = this.quotes.GetEma(this.period); Assert.Equal(Math.Round((double)SK.Last().Ema!, 8), Math.Round(QL.Last().v, 8)); } @@ -49,7 +49,7 @@ public class Skender_Stock public void WMA() { WMA_Series QL = new(this.bars.Close, this.period, false); - var SK = this.quotes.GetWma(this.period, CandlePart.Close); + var SK = this.quotes.GetWma(this.period); Assert.Equal(Math.Round((double)SK.Last().Wma!, 8), Math.Round(QL.Last().v, 8)); } @@ -76,7 +76,7 @@ public class Skender_Stock public void MAD() { MAD_Series QL = new(this.bars.Close, this.period, false); - var SK = this.quotes.GetSmaExtended(this.period); + var SK = this.quotes.GetSmaAnalysis(this.period); Assert.Equal(Math.Round((double)SK.Last().Mad!, 8), Math.Round(QL.Last().v, 8)); } @@ -85,7 +85,7 @@ public class Skender_Stock public void MAPE() { MAPE_Series QL = new(this.bars.Close, this.period, false); - var SK = this.quotes.GetSmaExtended(this.period); + var SK = this.quotes.GetSmaAnalysis(this.period); Assert.Equal(Math.Round((double)SK.Last().Mape!, 8), Math.Round(QL.Last().v, 8)); } diff --git a/Tests/Validations/TA_LIB.cs b/Tests/Validations/TA_LIB.cs index a464cd9b..ebfc1a68 100644 --- a/Tests/Validations/TA_LIB.cs +++ b/Tests/Validations/TA_LIB.cs @@ -6,7 +6,7 @@ using QuanTAlib; namespace Validation; public class TA_LIB { - private readonly RND_Feed bars; + private readonly GBM_Feed bars; private readonly Random rnd = new(); private readonly int period; private readonly double[] TALIB; diff --git a/docs/.md b/docs/.md new file mode 100644 index 00000000..d4f34736 --- /dev/null +++ b/docs/.md @@ -0,0 +1,87 @@ + +## 1. Prepare the Peloton tablet + +Stop Peloton overlay app: +- tap on Settings in the top right corner and select Device Settings +- tap Apps and scroll down to find and tap Peloton app (not Peloton Launcher, just Peloton) +- tap FORCE STOP to stop the app overlay +- confrm by tapping OK + +Turn on developer mode +- return to Settings page +- tap About tablet in System section +- tap Build number repeatedly until you activate developer mode + +Enable USB debugging +- return to Settings page +- tap (now visible) Developer options in System section +- scroll down to find USB Debugging option +- Enable USB debugging +- Confirm by tapping OK + +## 3. Prepare the PC with Zwift/Rouvy + +- Create your Splashtop account https://my.splashtop.com/login +- Download and install Splashtop Streamer https://www.splashtop.com/downloads#pers +- Download Android Platform Tools https://developer.android.com/studio/releases/platform-tools +- Download Nova launcher APK (or any other launcher that works on Android 7) https://apkpure.com/nova-launcher/com.teslacoilsw.launcher/download/62019-APK +- Download Splashtop APK https://apkpure.com/splashtop-personal-access/com.splashtop.remote.pad.v2 +- Unzip Android tools into a new folder +- move both APKs to the same folder +- Run Command Prompt (CMD) and move to the same folder +- Launch Android Debuging Bridge: adb start-server +- Connect PC and Peloton tablet with USB cable +- Peloton tablet will check for confirmation; Accept debugging over USB +- Verify connectivity on PC in the Command window: adb devices + +## 4. Side-load APKs + +- Execute the following three commands on PC: + adb shell settings put secure install_non_market_apps 1 + adb install + adb install +- Disconnect USB cable +- On Peloton tablet tap Peloton 'P' logo at the bottom +- Select Nova as a default launcher +- Accept all defaults for Nova launcher - you can customize it later + + +- (optional) Bring Peloton and Splashtop icons to the main page of Nova launcher +- Choosing Peloton launches Peloton app; Choosing Splashtop launches Splashtop app +- Swiping down from the top of the screen reveals the hidden 'P' launcher button + +## 5. Connect Peloton tablet and PC + +- Launch Splashtop app on Peloton tablet +- Login with Splashtop credentials +- Connect to PC that runs Splashtop streamer (and Zwift/Rouvy) +- Launch Zwift/Rouvy + +## 5. Enable sensors + +- (optional): buy ANT+ USB dongle https://www.amazon.com/s?k=ant%2B+USB+stick + +Peloton Tread: + Speed: Runn https://npe-inc.com/runn-smart-treadmill-sensor-2/ + (or Stryd https://www.stryd.com/us/en) + Cadence: Garmin foodpod (or Stryd) + Heartrate: any HR monitor (BT or ANT+) https://www.amazon.com/s?k=bluetooth+HR+monitor + Power: Stryd + +Peloton Bike (gen1): + Power & Cadence: DFC (Data Fitness Connector) https://www.crowdsupply.com/intelligenate/data-fitness-connector + Heartrate:vany HR monitor (BT or ANT+) + +## 6. Navigation + +Nova is now a default launcher on Android tablet, but on Tread we need to run Peloton app in the background to prevent locking of treadmill: + +- Launch Peloton app +- Swipe down from the top and return to Nova launcher +- Launch Splashtop app +- Connect to PC +- Launch Zwift or Rouvy +- Connect all sensors +- Run/Ride! + + \ No newline at end of file