Files
QuanTAlib/docs/getting_started.ipynb
T

12 KiB

Quick Start

In order to use this .NET Interactive Notebook and play along with QuanTAlib (outside of making your own app or plugging QuanTAlib into Quantower platform), you will need:

For impatient, here is a simple example of calculating three moving averages - SMA(data), EMA(SMA(data)) and WMA(EMA(SMA(data))) from 10 days of AAPL stock data using QuanTAlib:

In [1]:
#r "nuget:QuanTAlib;"
using QuanTAlib;

Yahoo_Feed aapl = new("AAPL", 10);
TSeries data = aapl.Close;
SMA_Series sma = new(source: data, period: 5, useNaN: false);
EMA_Series ema = new(sma, period: 5);                   // by default, indicators expose all data, no NaN values
WMA_Series wma = new(ema, 5, useNaN: true);             // for the final calculation we can hide early data with NaNs

Console.Write($"index\t data\t\t sma(data)\t ema(sma(data))\t wma(ema(sma(data)))\n");
for (int i=0; i<aapl.Count; i++)
    Console.Write($"{i}\t {data[i].t:yyyy-MM-dd}\t {sma[i].v:f2}\t\t {ema[i].v:f2}\t\t {wma[i].v:f2}\n");
(3,1): error CS0246: The type or namespace name 'Yahoo_Feed' could not be found (are you missing a using directive or an assembly reference?)

(10,15): error CS0019: Operator '<' cannot be applied to operands of type 'int' and 'method group'

Understanding QuanTAlib data model

QuanTAlib expects that every data item is a tuple (TimeDate t, double v) and TSeries is a list of (t,v) tuples. There are several helpers built into the TSeries class to simplify adding elements:

In [10]:
var item1 = (DateTime.Today, 105.3);        // (DateTime, Value) tuple
double item2 = 293.1;                       // a simple double

TSeries data = new();
data.Add(item1);                            // adding tuple variable
data.Add(item2);                            // QuanTAlib stamps the (double) with current time
data.Add(0);                                // directly adding a number (stamped with current time)
data.Add((DateTime.Now.AddDays(-3), 10));   // adding a tuple with timestamp 3 days ago

data
indexItem1Item2
02022-11-10 00:00:00Z
105.3
12022-11-10 15:47:46Z
293.1
22022-11-10 15:47:46Z
0
32022-11-07 15:47:46Z
10

TSeries list can display only values (without timestamps) or only timestamps (without values) by using .v or .t properties

In [11]:
data.v
indexvalue
0
105.3
1
293.1
2
0
3
10

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

In [12]:
bool IsTheSame = data.Last().v == data[^1].v;
double lastvalue = data;

lastvalue
10

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:

In [13]:
TSeries t1 = new() {0,1,2,3,4,5,6,7,8,9}; // t1 is loaded with data and activated as a publisher
EMA_Series t2 = new(t1, 3);     // t2 will auto-load all history of t1 and wait for events from t1
ADD_Series t3 = new(t1, t2);    // t3 is an ADDition of t1 and t2 - will also load history and wait for t2 events
DIV_Series t4 = new(1, t3);     // t4 is calculating 1/t3 - and waiting for t3 events

TSeries t5 = new();             // a wild indicator appeared! And it is empty!
t4.Pub += t5.Sub;               // let us add a manual subscription to events coming from t4 - t5 is now listening to t4
t1.Add(0);                      // we add one new value to t1 - and trigger the full cascade of calculation! t5 is now full!

t5.v
indexvalue
0
Infinity
1
0.6666666666666666
2
0.3333333333333333
3
0.2
4
0.14285714285714285
5
0.1111111111111111
6
0.09090909090909091
7
0.07692307692307693
8
0.06666666666666667
9
0.058823529411764705
10
0.25

MACD compounded indicator

With QuanTAlib we can chain indicators together, creating complex compounded indicators. For example, we can create Moving Average Convergence/Divergence (MACD) indicators by chaining all required operations in a sequence:

In [15]:
Yahoo_Feed aapl = new("AAPL", 100);
TSeries close = aapl.Close;                 // close will get data from history
EMA_Series slow = new(close,26);            // slow gets data from slow through pub-sub eventing
EMA_Series fast = new(close,12);            // fast gets data from slow (via eventing)
SUB_Series macd = new(fast,slow);           // macd is a SUBtraction: fast-slow
EMA_Series signal = new(macd,9);            // signal is EMA of macd
SUB_Series histogram = new(macd, signal);   // histogram is SUBtraction macd-signal

histogram.v
indexvalue
0
0
1
0
2
0
3
0
4
0
5
0
6
0
7
0
8
0
9
0
10
0
11
0
12
0.13543589743590018
13
-0.03897954353340993
14
-0.17731008431411102
15
-0.24030671152304095
16
-0.08247055673614988
17
-0.47898448490240814
18
-0.9020715041856615
19
-1.3489730137363423
(51 more)