new: EQUITY_Series

Add new EQUITY_Series and updates to docs, Calculations, Indicators, Strategies, Tests, and .github/workflows
This commit is contained in:
Miha Kralj
2023-04-07 16:49:59 -07:00
parent cb5fe2dc86
commit 34997cd0d6
11 changed files with 741 additions and 110 deletions
+260 -87
View File
@@ -2,14 +2,7 @@
"cells": [
{
"cell_type": "markdown",
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"polyglot_notebook": {
"kernelName": "csharp"
}
},
"metadata": {},
"source": [
"# Quick Start\n",
"\n",
@@ -24,16 +17,39 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 1,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [],
"outputs": [
{
"data": {
"text/html": [
"<div><div></div><div></div><div></div></div>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"index\t data\t\t sma(data)\t ema(sma(data))\t wma(ema(sma(data)))\n",
"0\t 2023-03-27\t 158.28\t\t 158.28\t\t NaN\n",
"1\t 2023-03-28\t 157.97\t\t 158.12\t\t NaN\n",
"2\t 2023-03-29\t 158.90\t\t 158.38\t\t NaN\n",
"3\t 2023-03-30\t 159.77\t\t 158.73\t\t NaN\n",
"4\t 2023-03-31\t 160.79\t\t 159.14\t\t 158.69\n",
"5\t 2023-04-03\t 162.37\t\t 160.22\t\t 159.25\n",
"6\t 2023-04-04\t 163.97\t\t 161.47\t\t 160.10\n",
"7\t 2023-04-05\t 164.56\t\t 162.50\t\t 161.07\n",
"8\t 2023-04-06\t 165.02\t\t 163.34\t\t 162.04\n"
]
}
],
"source": [
"#r \"nuget:QuanTAlib;\"\n",
"using QuanTAlib;\n",
@@ -51,14 +67,7 @@
},
{
"cell_type": "markdown",
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"polyglot_notebook": {
"kernelName": "csharp"
}
},
"metadata": {},
"source": [
"## Understanding QuanTAlib data model\n",
"\n",
@@ -67,16 +76,54 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 2,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [],
"outputs": [
{
"data": {
"text/html": [
"<table><thead><tr><th><i>index</i></th><th>value</th></tr></thead><tbody><tr><td>0</td><td><details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>(4/7/2023 12:00:00 AM, 105.3)</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Item1</td><td><span>2023-04-07 00:00:00Z</span></td></tr><tr><td>Item2</td><td><div class=\"dni-plaintext\"><pre>105.3</pre></div></td></tr></tbody></table></div></details></td></tr><tr><td>1</td><td><details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>(4/7/2023 2:34:48 PM, 293.1)</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Item1</td><td><span>2023-04-07 14:34:48Z</span></td></tr><tr><td>Item2</td><td><div class=\"dni-plaintext\"><pre>293.1</pre></div></td></tr></tbody></table></div></details></td></tr><tr><td>2</td><td><details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>(4/7/2023 2:34:48 PM, 0)</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Item1</td><td><span>2023-04-07 14:34:48Z</span></td></tr><tr><td>Item2</td><td><div class=\"dni-plaintext\"><pre>0</pre></div></td></tr></tbody></table></div></details></td></tr><tr><td>3</td><td><details class=\"dni-treeview\"><summary><span class=\"dni-code-hint\"><code>(4/4/2023 2:34:48 PM, 10)</code></span></summary><div><table><thead><tr></tr></thead><tbody><tr><td>Item1</td><td><span>2023-04-04 14:34:48Z</span></td></tr><tr><td>Item2</td><td><div class=\"dni-plaintext\"><pre>10</pre></div></td></tr></tbody></table></div></details></td></tr></tbody></table><style>\r\n",
".dni-code-hint {\r\n",
" font-style: italic;\r\n",
" overflow: hidden;\r\n",
" white-space: nowrap;\r\n",
"}\r\n",
".dni-treeview {\r\n",
" white-space: nowrap;\r\n",
"}\r\n",
".dni-treeview td {\r\n",
" vertical-align: top;\r\n",
" text-align: start;\r\n",
"}\r\n",
"details.dni-treeview {\r\n",
" padding-left: 1em;\r\n",
"}\r\n",
"table td {\r\n",
" text-align: start;\r\n",
"}\r\n",
"table tr { \r\n",
" vertical-align: top; \r\n",
" margin: 0em 0px;\r\n",
"}\r\n",
"table tr td pre \r\n",
"{ \r\n",
" vertical-align: top !important; \r\n",
" margin: 0em 0px !important;\r\n",
"} \r\n",
"table th {\r\n",
" text-align: start;\r\n",
"}\r\n",
"</style>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"var item1 = (DateTime.Today, 105.3); // (DateTime, Value) tuple\n",
"double item2 = 293.1; // a simple double\n",
@@ -92,60 +139,122 @@
},
{
"cell_type": "markdown",
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"polyglot_notebook": {
"kernelName": "csharp"
}
},
"metadata": {},
"source": [
"TSeries list can display only values (without timestamps) or only timestamps (without values) by using `.v` or `.t` properties"
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 3,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [],
"outputs": [
{
"data": {
"text/html": [
"<div class=\"dni-plaintext\"><pre>[ 105.3, 293.1, 0, 10 ]</pre></div><style>\r\n",
".dni-code-hint {\r\n",
" font-style: italic;\r\n",
" overflow: hidden;\r\n",
" white-space: nowrap;\r\n",
"}\r\n",
".dni-treeview {\r\n",
" white-space: nowrap;\r\n",
"}\r\n",
".dni-treeview td {\r\n",
" vertical-align: top;\r\n",
" text-align: start;\r\n",
"}\r\n",
"details.dni-treeview {\r\n",
" padding-left: 1em;\r\n",
"}\r\n",
"table td {\r\n",
" text-align: start;\r\n",
"}\r\n",
"table tr { \r\n",
" vertical-align: top; \r\n",
" margin: 0em 0px;\r\n",
"}\r\n",
"table tr td pre \r\n",
"{ \r\n",
" vertical-align: top !important; \r\n",
" margin: 0em 0px !important;\r\n",
"} \r\n",
"table th {\r\n",
" text-align: start;\r\n",
"}\r\n",
"</style>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"data.v"
]
},
{
"cell_type": "markdown",
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"polyglot_notebook": {
"kernelName": "csharp"
}
},
"metadata": {},
"source": [
"The last element on the list can be accessed by .Last() or by [^1] - and using `.t` (time) and `.v` (value) properties. Also, casting a TSeries into (double) will return the value of the last element"
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 4,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [],
"outputs": [
{
"data": {
"text/html": [
"<div class=\"dni-plaintext\"><pre>10</pre></div><style>\r\n",
".dni-code-hint {\r\n",
" font-style: italic;\r\n",
" overflow: hidden;\r\n",
" white-space: nowrap;\r\n",
"}\r\n",
".dni-treeview {\r\n",
" white-space: nowrap;\r\n",
"}\r\n",
".dni-treeview td {\r\n",
" vertical-align: top;\r\n",
" text-align: start;\r\n",
"}\r\n",
"details.dni-treeview {\r\n",
" padding-left: 1em;\r\n",
"}\r\n",
"table td {\r\n",
" text-align: start;\r\n",
"}\r\n",
"table tr { \r\n",
" vertical-align: top; \r\n",
" margin: 0em 0px;\r\n",
"}\r\n",
"table tr td pre \r\n",
"{ \r\n",
" vertical-align: top !important; \r\n",
" margin: 0em 0px !important;\r\n",
"} \r\n",
"table th {\r\n",
" text-align: start;\r\n",
"}\r\n",
"</style>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"bool IsTheSame = data.Last().v == data[^1].v;\n",
"double lastvalue = data;\n",
@@ -155,30 +264,61 @@
},
{
"cell_type": "markdown",
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"polyglot_notebook": {
"kernelName": "csharp"
}
},
"metadata": {},
"source": [
"All indicators are just modified TSeries classes; they get all required input during class construction (source of the datafeed, period...) and they automatically subscribe to events of the datafeed. Whenever datafeed gets a new value, indicator will calculate its own value. Indicators are also event publishers, so other indicators can subscribe to their results, chaining indicators together:"
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 5,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [],
"outputs": [
{
"data": {
"text/html": [
"<div class=\"dni-plaintext\"><pre>[ Infinity, 0.6666666666666666, 0.3333333333333333, 0.2, 0.14285714285714285, 0.1111111111111111, 0.09090909090909091, 0.07692307692307693, 0.06666666666666667, 0.058823529411764705, 0.25 ]</pre></div><style>\r\n",
".dni-code-hint {\r\n",
" font-style: italic;\r\n",
" overflow: hidden;\r\n",
" white-space: nowrap;\r\n",
"}\r\n",
".dni-treeview {\r\n",
" white-space: nowrap;\r\n",
"}\r\n",
".dni-treeview td {\r\n",
" vertical-align: top;\r\n",
" text-align: start;\r\n",
"}\r\n",
"details.dni-treeview {\r\n",
" padding-left: 1em;\r\n",
"}\r\n",
"table td {\r\n",
" text-align: start;\r\n",
"}\r\n",
"table tr { \r\n",
" vertical-align: top; \r\n",
" margin: 0em 0px;\r\n",
"}\r\n",
"table tr td pre \r\n",
"{ \r\n",
" vertical-align: top !important; \r\n",
" margin: 0em 0px !important;\r\n",
"} \r\n",
"table th {\r\n",
" text-align: start;\r\n",
"}\r\n",
"</style>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"TSeries t1 = new() {0,1,2,3,4,5,6,7,8,9}; // t1 is loaded with data and activated as a publisher\n",
"EMA_Series t2 = new(t1, 3); // t2 will auto-load all history of t1 and wait for events from t1\n",
@@ -194,14 +334,7 @@
},
{
"cell_type": "markdown",
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"polyglot_notebook": {
"kernelName": "csharp"
}
},
"metadata": {},
"source": [
"# MACD compounded indicator\n",
"\n",
@@ -210,16 +343,54 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 6,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [],
"outputs": [
{
"data": {
"text/html": [
"<div class=\"dni-plaintext\"><pre>[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -0.000974358974349343, -0.03456027049873228, -0.13792617985566447, -0.4729486712049916, -0.825402881197467, -0.8902360596814031, -0.9360607784903126, -0.7333381872239422 ... (79 more) ]</pre></div><style>\r\n",
".dni-code-hint {\r\n",
" font-style: italic;\r\n",
" overflow: hidden;\r\n",
" white-space: nowrap;\r\n",
"}\r\n",
".dni-treeview {\r\n",
" white-space: nowrap;\r\n",
"}\r\n",
".dni-treeview td {\r\n",
" vertical-align: top;\r\n",
" text-align: start;\r\n",
"}\r\n",
"details.dni-treeview {\r\n",
" padding-left: 1em;\r\n",
"}\r\n",
"table td {\r\n",
" text-align: start;\r\n",
"}\r\n",
"table tr { \r\n",
" vertical-align: top; \r\n",
" margin: 0em 0px;\r\n",
"}\r\n",
"table tr td pre \r\n",
"{ \r\n",
" vertical-align: top !important; \r\n",
" margin: 0em 0px !important;\r\n",
"} \r\n",
"table th {\r\n",
" text-align: start;\r\n",
"}\r\n",
"</style>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"Yahoo_Feed aapl = new(\"AAPL\", 100);\n",
"TSeries close = aapl.Close; // close will get data from history\n",
@@ -239,29 +410,31 @@
"language": "C#",
"name": ".net-csharp"
},
"language_info": {
"name": "polyglot-notebook"
},
"polyglot_notebook": {
"kernelInfo": {
"defaultKernelName": "csharp",
"items": [
{
"aliases": [
"c#",
"C#"
"C#",
"c#"
],
"languageName": "C#",
"name": "csharp"
},
{
"aliases": [
"frontend"
],
"languageName": null,
"name": "vscode"
},
{
"aliases": [],
"languageName": "KQL",
"name": "kql"
},
{
"aliases": [
"frontend"
],
"name": "vscode"
}
]
}