If you have any question or suggestion, we are happy to help and improve! Please email us at support@tradingmaps.co.
TradingMaps programming language is a basic and yet fast scripting language to create your own customized visualizations using available financial data.
The language provides basic arithmetic operations and built-in functions for data retrieval, mathematical computations and pixel maps. It also includes control structures like basic for loops and if-else statements.
A typical program is structured this way:
Get Data Calculate Fill Pixel Map
Built-in functions help you fetch the latest candlesticks (up to 500 per ticker per timeframe for now) as well as other data points, load all this into arrays and matrices, perform free calculations and fill in the pixel map. Your script is interpreted server-side by C++ so calculations are fast.
This technical documentation guides you through the language's features and syntax, helping you get started quickly.
Are you ready? Let's go!
In the coding language, you have access to a wide range of financial data for analysis and computations. The following data is currently available:
Timeframes available for data retrieval are the following ones:
Please note that the available financial data is subject to change in the coming weeks as more data may be added based on demand and requirements.
In TradingMaps Language, you can define simple variables. Types are int, double and string. Here's an example:
int x = 10;
double y = 3.14;
string name = "John";
In the above example, we defined an int
variable x
and assigned it the value 10. Similarly, we defined a double
variable y
with the value 3.14, and a string
variable name
with the value "John".
TradingMaps Language supports arrays and matrices.
You can define arrays using the newarrayint
, newarraydouble
, or newarraystring
functions, and matrices using the newmatrixint
or newmatrixdouble
functions. Here are some examples:
arrayint arr = newarrayint(10);
matrixdouble mat = newmatrixdouble(m, n);
The above example create a new arrayint
named arr
with a size of 10 elements, and a new matrixdouble
named mat
with m
rows and n
columns. You can access array elements and matrix elements using the square bracket notation. Here's an example:
To access an individual element of an array, use the name of the array name followed by the index of the element in square brackets
Same for access to an individual element of a matrix: use a second pair of square brackets.
Note that you cannot use a matrix "row" or "column" as an array in TradingMaps language. You cannot use something like arrayint a = m[0];
. Access to any matrix element must use two pairs of square brackets like m[i][j]
.
int value = arr[0];
double element = mat[i][j];
In the above example, we accessed the first element of the arrayint arr
using arr[0]
, and a specific element in the matrixdouble mat
using mat[i][j]
.
TradingMaps Language supports very basic for loops and if statements for control flow. Here's an example of a loop:
int i;
for (i = 0; i < n; i = i + 1) {
// Instructions to be executed in each iteration
}
In the above example, we defined a loop using the for
statement. The loop iterates from i = 0
to i < n
, incrementing i
by 1 in each iteration. You can place your instructions inside the curly braces to be executed in each iteration.
TradingMaps Language also supports conditional statements using the if
statement. Here's an example:
if (a <= 3) {
// Instructions to be executed if the condition is true
} else if (a <= 6) {
// Instructions to be executed if the condition is true
} else {
// Instructions to be executed if no condition is true
}
In the above example, we used the if
, else if
, and else
statements to perform different actions based on the condition. You can replace the conditions and instructions with your own logic.
TradingMaps Language allows you to define custom functions to perform specific calculations or operations. You can create functions with different parameter types, including int
, double
, string
, arrayint
, arraydouble
, arraystring
, matrixint
, matrixdouble
, and matrixstring
.
Here's an example of a custom function that takes a double
parameter and returns a double
value:
double f(double x) {
return x * x;
}
In the above example, we defined a custom function called f
that takes a double
parameter x
. The function calculates the square of x
by multiplying it with itself and returns the result.
Additionally, if a function doesn't return any value, its return type should be void
.
Let's look at another example:
arrayint a = newarrayint(10); // Initialize an array of length 10
int i;
void fillArray(arrayint a2) {
for (i = 0; i < 10; i = i + 1) {
a2[i] = // Calculate i-th element ...
}
}
// Call your function
fillArray(a);
The code above demonstrates an example of a function called fillArray
. It takes an arrayint
parameter named a2
. The purpose of this function is to fill the elements of the array with some calculated values.
It's important to note that the parameter name a2
must be different from any existing global variable names. This ensures that the local variable a2
inside the function doesn't conflict with the global variable a
.
As you can see in the code, both the arrayint
variable a
and the int
variable i
are defined globally outside the function. This is because all the needed variables should be defined globally in the TradingMaps language.
TradingMaps Language provides built-in functions for basic math operations. For example, you can use mini()
to return the minimum of two integers, min()
for two doubles, and so on. Each function has a specific name depending on the data type it operates on. Here's an example:
int result = mini(a, b);
double value = min(x, y);
In the above example, we used the mini()
function to get the minimum value between 2 ints a
and b
, and the min()
function to get the minimum value between 2 doubles x
and y
.
The setpixelmapdims
function is used to set the dimensions of the pixel map. It takes two parameters: the width and height of the map.
setpixelmapdims(3, 3);
In the above example, the setpixelmapdims
function sets the pixel map dimensions to a width of 3 and a height of 3.
Note that you have access to the HTML pixel map container's dimensions in pixel via built-in variables container_dim_x
and container_dim_y
. You can set pixel map dimensions depending on these.
For example like this to account for various screen size:
int pixel_map_dim_y = 30;
int pixel_map_dim_x = 50;
if (container_dim_x < 800) {pixel_map_dim_x = 20;} // pixel map for mobile, show a bit less pixels (tickers for example)
if (container_dim_x < 350) {pixel_map_dim_x = 10;} // thumbnail version
setpixelmapdims(pixel_map_dim_x, pixel_map_dim_y);
The setpixelijcolor
function is used to set the color of a specific pixel on the map. It takes three parameters: the zero-based x-coordinate and y-coordinate in the pixel map of dimensions set by setpixelmapdims
, and the RGB components of the color as 3 ints expected to be in [0,255].
setpixelijcolor(1, 1, 0, 0, 0);
In the above example, the setpixelijcolor
function sets the color of the pixel at coordinates (1, 1) to black (RGB: 0, 0, 0).
The pixel map coordinate system is cartesian with the origin pixel of coordinates (0;0) at the bottom left corner of the screen.
The setpixelijtexts
function is used to set the texts displayed on a specific pixel. It takes multiple parameters: the zero-based x-coordinate and y-coordinate in the pixel map of dimensions set by setpixelmapdims
, primary text, primary text color (RGB), secondary text, and secondary text color (RGB).
The pixel map coordinate system is cartesian with the origin pixel of coordinates (0;0) at the bottom left corner of the screen.
setpixelijtexts(1, 1, "Quick", 255, 255, 255, "Start", 255, 255, 255);
In the above example, the setpixelijtexts
function sets the primary text of the pixel at coordinates (1, 1) to "Quick" with white color (RGB: 255, 255, 255), and the secondary text to "Start" with white color as well.
tickersdata
is an important function used to retrieve tickers' candlestick data for a specified number of tickers. It takes multiple parameters: tickers query string, number of tickers, timeframe, candlestick limit, requested fields, matrix for strings, and matrix for doubles (candlestick ohlcv values).
Return value is the actual number of fetched tickers.
In case of any error or in case of no matching ticker, tickersdata
returns -1.
// Fetch data for 20 tickers
int nb_tickers = 20;
// Tickers query string
string tickers_str = "market=crypto, symbol not in (adadown,adaup, bnbdown,bnbup, btcdown,btcup, ethdown,ethup, xrpdown,xrpup, aud,gbp,eur, paxg, busd,usdc,usdp,tusd), quote in(usdt), marketcap in [0, " + i2s(nb_tickers) + "]";
int nb_last_candlesticks = 100;
// Variables to store data
matrixstring mats = newmatrixstring(nb_tickers, 2); // Why 2? See "symbol, quote" in tickersdata() below
matrixdouble matd = newmatrixdouble(nb_tickers * 4, nb_last_candlesticks); // Why 4? See "o,h,l,c" in tickersdata() below. We do not query the volume here.
fillmatrixd(matd, 0.0);
// Fetch data
// Note that the returned number of tickers may be lesser than 20 if there is less than 20 tickers matching the query string.
nb_tickers = tickersdata(tickers_str, nb_tickers, timeframe, "last " + i2s(nb_last_candlesticks), "symbol, quote", "o,h,l,c", mats, matd);
//error check
if (nb_tickers == -1) {
error("Either there is no data, or tickersdata() failed or timed out because a bit too much data is requested."); // if an error occurs in tickersdata(), it returns -1 and error() displays the error message in red client-side
}
// Do whatever you need with data contained in mats and matd ...
In the above example, the tickersdata
function is used to fetch the last 100 candlestick ohlc data for 20 tickers in the cryptocurrency market. The data includes the symbols, quotes, and candlestick open, high, low and close values for the specified timeframe and candlestick limit. The retrieved data is stored in matrices mats
and matd
.
First, tickersdata
does not sort tickers in any particular order. Only the candlestick data in matd
is sorted from oldest to latest. We are going to see how just below.
In the above example, mats
matrix contains one ticker data per row. The first column contains the symbols. The second column contains the quote asset ("USDT" in this example, see tickers_str
).
So, to access i-th ticker's symbol and quote asset, use string symbol = mats[i][0];
and string quote = mats[i][1];
. We use 0
and 1
column index in matrix mats
respectively because the order "symbol, quote"
was used in the call to tickersdata
.
matd
matrix is structured a bit differently to host time series but not much. Each set of 4 consecutive rows in matd
represent one ticker's ohlc data.
So, because we used "o,h,l,c"
in the tickersdata
call above:
Row at index 4*i + 0
contains the open values.
So access the nb_last_candlesticks
open values using double open = matd[4*i][j]
, j
being the index of the candlestick,
Row at index 4*i + 1
contains the high values.
Access the nb_last_candlesticks
high values using double high = matd[4*i + 1][j]
,
Row at index 4*i + 2
contains the low values.
Access the nb_last_candlesticks
low values using double low = matd[4*i + 2][j]
,
Row at index 4*i + 3
contains the close values.
Access the nb_last_candlesticks
close values using double close = matd[4*i + 3][j]
.
If you only want close prices, call tickersdata
with "c"
and simply use matd[i][j]
to i-th ticker's j-th close price.
This retrieves top 100 Binance USDT cryptos, with some hand-picked exceptions, and calculates the daily candlestick returns:
int nb_tickers = 100; // default number of queried tickers
int nb_last_values = 1;
string timeframe = "1d"; // daily timeframe
matrixstring mats = newmatrixstring(nb_tickers, 1/*symbol*/);
matrixdouble matd = newmatrixdouble(2/*open, close*/ * nb_tickers, nb_last_values);
//Please be careful on syntax here, field count must match matrices' dimensions above, no useless comma... etc
string tickers_str = "market=crypto, symbol not in (adadown,adaup, bnbdown,bnbup, btcdown,btcup, ethdown,ethup, xrpdown,xrpup, aud,gbp,eur, paxg, busd,usdc,usdp,tusd), quote in (usdt), marketcap in [0, "+i2s(nb_tickers)+"]";
nb_tickers = tickersdata(tickers_str , nb_tickers, timeframe, "last "+i2s(nb_last_values), "symbol", "o, c", mats, matd);
//error check
if (nb_tickers == -1) {
error("Either there is no data, or tickersdata() failed or timed out because a bit too much data is requested.");
}
arraydouble candlestick_return_arr = newarraydouble(nb_tickers);
int i;
double open;
double close;
double candlestick_return;
for (i = 0; i < nb_tickers ; i=i+1) {
open = matd[2*i+0][nb_last_values-1]; // note how we access the latest open value
close = matd[2*i+1][nb_last_values-1]; // note how we access the latest close value
candlestick_return = (close - open) / open;
candlestick_return_arr[i] = candlestick_return;
// do whatever you want with i-th ticker's daily candlestick return...
}
The tickers query string in the `tickersdata()` function allows you to retrieve data for specific tickers based on various criteria. Let's explore the different elements and syntax of the tickers query string:
A ticker consists of several components, including the market type, symbol, and quote asset. The query string can include fields like market, symbol, quote, market_type, source, and marketcap.
These fields can be used in the query string to filter and retrieve specific tickers based on your requirements.
Operators that can be used in the query string include "=", "!=", "in", and "not in". These operators allow you to filter and match specific criteria in your ticker data. However, there is an exception for the "marketcap" field, which follows a slightly different syntax.
The "=" operator is used to match exact values. For example, if you want to retrieve data for tickers with a specific symbol, you can use the "=" operator like this:
"symbol = btc"
The "!=" operator is used to exclude specific values. For example, if you want to retrieve data for crypto tickers excluding certain symbols like "ada" and "bnb", you can use the "!=" operator like this:
"symbol not in (ada, bnb)"
The "in" operator is used to match values from a list. For example, if you want to retrieve data for tickers with specific quotes like "usdt" or "usdc", you can use the "in" operator like this:
"quote in (usdt, usdc)"
The "not in" operator is used to exclude values from a list. For example, if you want to retrieve data for crypto tickers excluding specific quotes like "usdt" or "usdc", you can use the "not in" operator like this:
"quote not in (usdt, usdc)"
TODO MAKE A TIP It's important to note that the "in" and "not in" operators for the "marketcap" field expect an unordered list of strings, without the need for quotes or double quotes.
Now, let's talk about the "marketcap" field. The "marketcap" field is special and uses the syntax "in []". It allows you to retrieve tickers based on their market capitalization ranking. For example, if you want to retrieve the top 100 tickers by market capitalization, you can use the "marketcap" field like this:
"marketcap in [0, 100]"
In this example, the range specified in square brackets "[0, 100]" represents the market capitalization ranking range.
These operators and their examples demonstrate how you can use the query string to filter and retrieve specific ticker data based on various criteria.
Let's look at some examples to better understand the query string usage:
// Retrieve data for crypto tickers excluding specific symbols
string query1 = "market=crypto, symbol not in (adadown, adaup, bnbdown, bnbup, btcdown, btcup, ethdown, ethup, xrpdown, xrpup, aud, gbp, eur, paxg, busd, usdc, usdp, tusd), quote in (usdt), marketcap in [0, " + i2s(nb_tickers) + "]";
Retrieve data for crypto tickers, excluding specific symbols like "adadown", "adaup", "bnbdown", and others. The tickers should have the quote asset "usdt" and fall within the marketcap ranking of the first 100. The query string syntax demonstrates the use of the "not in" operator and the "marketcap" field with the "in" syntax.
// Retrieve data for a specific ticker
string handle_symbol = "btc";
string quote = "usdt";
string source = "binance";
string tickers_str = "symbol=" + handle_symbol + ", quote=" + quote + ", market_type=spot, source=" + source;
Retrieve data for a specific ticker. The variables handle_symbol
, quote
, and source
are used to construct the query string. This example showcases the usage of the "symbol", "quote", "market_type", and "source" fields.
Feel free to modify the query string and adjust the parameters based on your specific requirements to fetch the desired ticker data using the `tickersdata()` function.
You must use appropriate conversion built-in functions when you want to store a double into an int, an int into a double, a int into a string... etc.
The d2i
function converts a double to an integer.
// Convert a double value to an integer
double num = 3.14;
int converted = d2i(num);
The i2d
function converts an integer to a double.
// Convert an integer value to a double
int num = 5;
double converted = i2d(num);
The i2s
function converts an integer to a string.
// Convert an integer value to a string
int num = 10;
string converted = i2s(num);
The d2s
function converts a double to a string.
// Convert a double value to a string
double num = 3.14159;
string converted = d2s(num);
The s2i
function converts a string to an integer.
// Convert a string value to an integer
string num = "42";
int converted = s2i(num);
The s2d
function converts a string to a double.
// Convert a string value to a double
string num = "3.14";
double converted = s2d(num);
The upper
function converts a string to uppercase.
// Convert a string to uppercase
string text = "hello world";
string uppercase = upper(text);
After executing the code block, the value of uppercase
will be "HELLO WORLD".
The lower
function converts a string to lowercase.
// Convert a string to lowercase
string text = "Hello World";
string lowercase = lower(text);
After executing the code block, the value of lowercase
will be "hello world".
The newarrayint
function creates a new array of integers with a specified length.
// Create a new array of integers with length 5
arrayint arr = newarrayint(5);
After executing the code block, the variable arr
will be a new array of integers with a length of 5.
The newarraydouble
function creates a new array of doubles with a specified length.
// Create a new array of doubles with length 10
arraydouble arr = newarraydouble(10);
After executing the code block, the variable arr
will be a new array of doubles with a length of 10.
The newarraystring
function creates a new array of strings with a specified length.
// Create a new array of strings with length 3
arraystring arr = newarraystring(3);
After executing the code block, the variable arr
will be a new array of strings with a length of 3.
The leni
function returns the length of an array of integers.
// Get the length of an array of integers
arrayint arr = newarrayint(5);
int length = leni(arr);
After executing the code block, the variable length
will contain the length of the array, which is 5 in this example.
The lend
function returns the length of an array of doubles.
// Get the length of an array of doubles
arraydouble arr = newarraydouble(5);
int length = lend(arr);
After executing the code block, the variable length
will contain the length of the array, which is 5 in this example.
The lens
function returns the length of an array of strings.
// Get the length of an array of strings
arraystring arr = newarraystring(3);
int length = lens(arr);
After executing the code block, the variable length
will contain the length of the array, which is 3 in this example.
The newmatrixint
function creates a new matrix of integers with the specified number of rows and columns.
// Create a new matrix of integers with 3 rows and 4 columns
matrixint mat = newmatrixint(3, 4);
After executing the code block, the variable mat
will contain a new matrix of integers with 3 rows and 4 columns.
The newmatrixdouble
function creates a new matrix of doubles with the specified number of rows and columns.
// Create a new matrix of doubles with 2 rows and 2 columns
matrixdouble mat = newmatrixdouble(2, 2);
After executing the code block, the variable mat
will contain a new matrix of doubles with 2 rows and 2 columns.
The newmatrixstring
function creates a new matrix of strings with the specified number of rows and columns.
// Create a new matrix of strings with 4 rows and 3 columns
matrixstring mat = newmatrixstring(4, 3);
After executing the code block, the variable mat
will contain a new matrix of strings with 4 rows and 3 columns.
The nbrowsi
function returns the number of rows in a matrix of integers.
// Get the number of rows in a matrix of integers
matrixint mat = newmatrixint(2, 3);
int numRows = nbrowsi(mat);
After executing the code block, the variable numRows
will contain the number of rows in the matrix, which is 2 in this example.
The nbcolsi
function returns the number of columns in a matrix of integers.
// Get the number of columns in a matrix of integers
matrixint mat = newmatrixint(2, 3);
int numCols = nbcolsi(mat);
After executing the code block, the variable numCols
will contain the number of columns in the matrix, which is 3 in this example.
The nbrowsd
function returns the number of rows in a matrix of doubles.
// Get the number of rows in a matrix of doubles
matrixdouble mat = newmatrixdouble(3, 2);
int numRows = nbrowsd(mat);
After executing the code block, the variable numRows
will contain the number of rows in the matrix, which is 3 in this example.
The nbcolsd
function returns the number of columns in a matrix of doubles.
// Get the number of columns in a matrix of doubles
matrixdouble mat = newmatrixdouble(3, 2);
int numCols = nbcolsd(mat);
After executing the code block, the variable numCols
will contain the number of columns in the matrix, which is 2 in this example.
The nbrowss
function returns the number of rows in a matrix of strings.
// Get the number of rows in a matrix of strings
matrixstring mat = newmatrixstring(2, 2);
int numRows = nbrowss(mat);
After executing the code block, the variable numRows
will contain the number of rows in the matrix, which is 2 in this example.
The nbcolss
function returns the number of columns in a matrix of strings.
// Get the number of columns in a matrix of strings
matrixstring mat = newmatrixstring(2, 2);
int numCols = nbcolss(mat);
After executing the code block, the variable numCols
will contain the number of columns in the matrix, which is 2 in this example.
The fillarrayi
function is used to fill a range of elements in an integer array with a specified value. Here is an example usage:
Returns nothing (void type).
fillarrayi(arr, i0, i1, val); // Fills the elements from index i0 to i1 (excluded) with the value val
The fillarrayd
function is used to fill a range of elements in a double array with a specified value. Here is an example usage:
Returns nothing (void type).
fillarrayd(arr, i0, i1, val); // Fills the elements from index i0 to i1 (excluded) with the value val
The fillarrays
function is used to fill a range of elements in a string array with a specified value. Here is an example usage:
Returns nothing (void type).
fillarrays(arr, i0, i1, val); // Fills the elements from index i0 to i1 (excluded) with the value val
The fillmatrixi
function is used to fill all elements of an integer matrix with a specified value. Here is an example usage:
Returns nothing (void type).
fillmatrixi(mat, val); // Fills the matrix with the value val
The fillmatrixd
function is used to fill all elements of a double matrix with a specified value. Here is an example usage:
Returns nothing (void type).
fillmatrixd(mat, 0.0); // Fills the matrix with the value 0.0
The sortarrayd
function is used to sort a double array in either ascending or descending order. It sorts the indices only. First, create an index array to keep track of the original order. Here is an example usage:
Returns nothing (void type).
// Create an index array
arrayint indices_arr = newarrayint(nb_tickers);
// Sort the double array in descending order and update the index array accordingly
// Note that 'values_arr' remains unchanged!
sortarrayd(values_arr, 1, indices_arr); //Use 0 for ascending order, 1 for descending order
In the above example, the sortarrayd
function sorts the values_arr
array in descending order. values_arr
remains unchanged, only the indices_arr
array is updated to reflect the new order after sorting.
The following math functions operate on integer values and return an integer result. They provide essential operations such as finding the maximum value, computing the absolute value, and clamping a value within a specified range.
// Find the maximum value between two integers.
int a = maxi(3, 5); // Returns 5
// Calculate the absolute value of an integer.
int a = absi(-7); // Returns 7
// Raise an integer to a power.
int a = powi(2, 3); // Returns 8
// Clamp an integer within a specified range.
int a = clampi(10, 0, 5); // Returns 5
The following math functions operate on double values and return a double result. They offer a variety of mathematical operations such as finding the minimum and maximum values, computing absolute values, powers, trigonometric functions, logarithms, rounding, and more.
Supported functions:
max
, abs
, pow
, floor
, ceil
, cos
, sin
, tan
, acos
, asin
, atan
, atan2
, log
, log10
, exp
, round
, clamp
.
You can use these functions in your TradingMaps code by invoking them with appropriate arguments. These math functions provide consistent behavior and return 0.0 in case of typical NaN (Not a Number) scenarios, ensuring reliable handling of such cases.
// Find the maximum value between two doubles.
double d = max(3.2, 5.7); // Returns 5.7
// Compute the absolute value of a double.
double d = abs(-2.5); // Returns 2.5
// Calculate the power of a double.
double d = pow(2.0, 3.0); // Returns 8.0
// Round down a double to the nearest integer.
double d = floor(5.7); // Returns 5.0
// Round up a double to the nearest integer.
double d = ceil(2.3); // Returns 3.0
// Compute the cosine of a double value.
double d = cos(0.0); // Returns 1.0
// Compute the natural logarithm of a double.
double d = log(10.0); // Returns approximately 2.30259
// Round a double to the nearest integer.
double d = round(2.6); // Returns 3.0
// Clamp a double within a specified range.
double d = clamp(10.5, 0.0, 5.0); // Returns 5.0
Remember that these functions return 0.0 in case of typical NaN (Not a Number) scenarios.
TradingMaps Language provides built-in functions for various indicators.
One such function is lastrsifrommatrix()
. This function calculates the Relative Strength Index (RSI) for each ticker based on the provided matrix of data.
The function signature for lastrsifrommatrix()
is as follows:
void lastrsifrommatrix(matrixdouble mat, int startRow, int rowStep, int indicatorLength, arraydouble resultArr);
The parameters for this function are:
tickersdata()
function. It may contain ohlcv time series, the open and close time series, or only the close time seriesmatd
from which RSI calculation should start.matd
.arraydouble
that will store the latest RSI values for each ticker. The length of this array is typically the number of tickers.
startRow and rowStep describe which time series rows you want to use from matd
. It's usually close prices, from oldest to latest values. But you can choose other values too.
Here's an example usage of lastrsifrommatrix()
:
arraydouble rsi_arr = newarraydouble(nb_tickers);
int rsi_length = 14;
lastrsifrommatrix(matd, 0, 1/*use 1, 2 if you queried "v, c" in tickersdata() call, or use 0, 5 if you queried "c,o,h,l,v" to calculate RSI on close prices*/, rsi_length, rsi_arr);
In the above example, we created a new arraydouble
called rsi_arr
to store the RSI values for each ticker. We specified an RSI length of 14 using the rsi_length
variable. Then, we called lastrsifrommatrix()
with the matrix matd
obtained from the tickersdata()
function, a start row index of 0 and a row step of 1 (if we queried only the close prices tickersdata(..., ..., "c", mats, matd);
), the RSI length, and the rsi_arr
array as the result container.
Another useful function is lastsmafrommatrix()
. This function calculates the Simple Moving Average (SMA) for each ticker based on the provided matrix of data.
The function signature for lastsmafrommatrix()
is as follows:
void lastsmafrommatrix(matrixdouble matd, int startRow, int rowStep, int indicatorLength, arraydouble resultArr);
The parameters for this function are:
tickersdata()
function. It may contain OHLCV time series, the open and close time series, or only the close time series.matd
from which SMA calculation should start.matd
.arraydouble
that will store the latest SMA values for each ticker. The length of this array is typically the number of tickers.
startRow and rowStep describe which time series rows you want to use from matd
. It's usually close prices, from oldest to latest values. But you can choose other values too.
Here's an example usage of lastsmafrommatrix()
:
arraydouble sma_arr = newarraydouble(nb_tickers);
int sma_length = 50;
lastsmafrommatrix(matd, 0, 1/*use 1, 2 if you queried "v, c" in tickersdata() call, or use 0, 5 if you queried "c,o,h,l,v" to calculate SMA on close prices*/, sma_length, sma_arr);
In the above example, we created a new arraydouble
called sma_arr
to store the SMA values for each ticker. We specified an SMA length of 50 using the sma_length
variable. Then, we called lastsmafrommatrix()
with the matrix matd
obtained from the tickersdata()
function, a start row index of 0 and a row step of 1 (if we queried only the close prices tickersdata(..., ..., "c", mats, matd);
), the SMA length, and the sma_arr
array as the result container.
Similar built-in function lastemafrommatrix()
.
Another useful function is lastbbfrommatrix()
. This function calculates the Bollinger Bands (BB) for each ticker based on the provided matrix of data.
The function signature for lastbbfrommatrix()
is as follows:
void lastbbfrommatrix(matrixdouble matd, int startRow, int rowStep, int indicatorLength, double bbDeviation, arraydouble upperBandArr, arraydouble middleBandArr, arraydouble lowerBandArr);
The parameters for this function are:
tickersdata()
function. It may contain OHLCV time series, the open and close time series, or only the close time series.matd
from which BB calculation should start.matd
.arraydouble
that will store the latest upper band values for each ticker. The length of this array is typically the number of tickers.arraydouble
that will store the latest middle band values for each ticker. The length of this array is typically the number of tickers.arraydouble
that will store the latest lower band values for each ticker. The length of this array is typically the number of tickers.
startRow and rowStep describe which time series rows you want to use from matd
. It's usually close prices, from oldest to latest values. But you can choose other values too.
Here's an example usage of lastbbfrommatrix()
:
arraydouble upper_band = newarraydouble(nb_tickers);
arraydouble middle_band = newarraydouble(nb_tickers);
arraydouble lower_band = newarraydouble(nb_tickers);
int bb_length = 20;
double bb_deviation = 2.0;
lastbbfrommatrix(matd, 0, 1/*use 1, 2 if you queried "v, c" in tickersdata() call, or use 0, 5 if you queried "c,o,h,l,v" to calculate BB on close prices*/, bb_length, bb_deviation, upper_band, middle_band, lower_band);
In the above example, we created three new arraydouble
variables: upper_band
, middle_band
, and lower_band
to store the upper band, middle band, and lower band values respectively for each ticker. We specified a BB length of 20 using the bb_length
variable, and a BB deviation of 2.0 using the bb_deviation
variable. Then, we called lastbbfrommatrix()
with the matrix matd
obtained from the tickersdata()
function, a start row index of 0 and a row step of 1 (if we queried only the close prices tickersdata(..., ..., "c", mats, matd);
), the BB length, BB deviation, and the respective arrays to store the calculated BB values.
The layoutbylinetopleft
function is used to convert indices to (i,j) coordinates and store them in a matrix. This function is typically used to create a pixel map layout based on a given set of indices. Indices are spread from pixel map top left pixel to bottom right pixel, line by line.
The function signature for layoutbylinetopleft
is as follows:
void layoutbylinetopleft(arrayint indices_arr, matrixint index_at_pixel_mat);
The parameters for this function are:
The layoutbylinetopleft
function maps the indices to the (i,j) coordinates of the pixel map. The function loops through the indices and assigns the corresponding coordinates to the matrix index_at_pixel_mat
.
Here's an example usage of layoutbylinetopleft
:
arrayint indices_arr = newarrayint(nb_tickers);
// Sort indexes by RSI
sortarrayd(rsi_arr, 1/*descending order*/, indices_arr);
// Build the pixel map layout
matrixint ticker_index_at_pixel_mat = newmatrixint(pixel_map_dim_x, pixel_map_dim_y);
fillmatrixi(ticker_index_at_pixel_mat, -1);
layoutbylinetopleft(indices_arr, ticker_index_at_pixel_mat);
In the above example, we first create an arrayint
called indices_arr
to store the indices. Then, we sort the previously-built rsi_arr
array in descending order using the sortarrayd
function and store the sorted indices in indices_arr
.
Next, we create a new matrixint
called ticker_index_at_pixel_mat
with dimensions pixel_map_dim_x
and pixel_map_dim_y
. We initialize the matrix with a value of -1 using the fillmatrixi
function to ensure empty cells have a default value. Then, we call the layoutbylinetopleft
function, passing the indices_arr
and ticker_index_at_pixel_mat
as arguments.
The layoutbylinetopleft
function maps the indices in indices_arr
to their corresponding (i,j) coordinates and stores them in ticker_index_at_pixel_mat
. Each index is accessed using two nested loops that iterate over the dimensions of the pixel map:
for (i = 0; i < pixel_map_dim_x; i = i + 1) {
for (j = 0; j < pixel_map_dim_y; j = j + 1) {
ticker_index = ticker_index_at_pixel_mat[i][j];
// If index is well defined, see how layout is built above
if (ticker_index != -1) {
rsi = rsi_arr[ticker_index];
// Rest of the code here
// ...
}
}
}
The diffuse2d
function is used to diffuse indices in a matrix starting from a seed point. This function is commonly used to spread or distribute indices across a two-dimensional space, such as a pixel map or grid.
The function signature for diffuse2d
is as follows:
void diffuse2d(arrayint indices_arr, arrayint seed_coords_arr, matrixint ticker_index_at_pixel_mat);
The parameters for this function are:
The diffuse2d
function spreads or diffuses the indices in the indices_arr
across the two-dimensional space represented by the ticker_index_at_pixel_mat
. The diffusion process starts from the seed point specified by the seed_coords_arr
.
Here's an example usage of diffuse2d
:
arrayint indices_arr = newarrayint(nb_tickers);
// Sort indexes by RSI
sortarrayd(rsi_arr, 1/*descending order*/, indices_arr);
arrayint seed_coords_arr = newarrayint(2);
seed_coords_arr[0] = (pixel_map_dim_x * user_x) / container_dim_x;
seed_coords_arr[1] = (pixel_map_dim_y * user_y) / container_dim_y;
matrixint ticker_index_at_pixel_mat = newmatrixint(pixel_map_dim_x, pixel_map_dim_y);
diffuse2d(indices_arr, seed_coords_arr, ticker_index_at_pixel_mat);
In the above example, we first create an arrayint
called indices_arr
to store the indices. Then, we sort the previously-built rsi_arr
array in descending order using the sortarrayd
function and store the sorted indices in indices_arr
.
Next, we create a new arrayint
called seed_coords_arr
with a length of 2. We calculate the seed coordinates by mapping the user-defined coordinates (user_x
and user_y
) to the dimensions of the container (container_dim_x
and container_dim_y
) and the pixel map (pixel_map_dim_x
and pixel_map_dim_y
). These coordinates determine the starting point of the diffusion process.
Then, we create a new matrixint
called ticker_index_at_pixel_mat
with dimensions pixel_map_dim_x
and pixel_map_dim_y
. This matrix will store the diffused indices as the result of the diffusion process.
Finally, we call the diffuse2d
function, passing the indices_arr
, seed_coords_arr
, and ticker_index_at_pixel_mat
as arguments. The function will diffuse the indices starting from the seed point and store the results in the ticker_index_at_pixel_mat
matrix.
The diffuse2d
function spreads the indices in the indices_arr
across the two-dimensional space represented by the ticker_index_at_pixel_mat
. It employs an algorithm to propagate the indices from the seed point to neighboring cells, gradually filling the matrix with the diffused indices.
I hope this explanation clarifies the functionality of the diffuse2d
function and how it can be used to spread indices across the pixel map.
If you are not satisfied by built-in sorting functions, you can always invent your own one. You could layout by column, by polar coordinates, use other filtering features like tickers' categories, or only filter out the vast majority of the data and only display the most relevant results on the pixel map...
The error()
function is used to display error messages in red on the client-side. It is commonly used to handle and communicate errors that occur during the execution of the program or a specific function.
Here's a typical example of using the error()
function:
// Error check just after tickersdata() call
if (nb_tickers == -1) {
error("Either there is no data, or tickersdata() failed or timed out because a bit too much data is requested.");
}
In the above example, the error()
function is used to display an error message client-side. If the value of nb_tickers
is -1 after a call to nb_tickers = tickersdata(...)
, indicating an error in the tickersdata()
function. This message will be displayed in red on the client-side, alerting the user about the error.
Particle Mode is a special drawing mode that can be enabled client-side. You can see an example here. It offers a unique way to visualize your data or create interesting effects using particles or "bubbles." This mode allows you to create and manipulate particles on a pixel map.
To begin, you start with a black pixel map of dimensions 'pixel_map_dim_x' and 'pixel_map_dim_y' that you set. All pixels are initially "off," meaning no particles are present.
To create a particle, you can set specific pixels on the pixel map. Let's start by setting the center pixel to white using the following code:
setpixelijcolor(pixel_map_dim_x/2, pixel_map_dim_y/2, 255, 255, 255);
setpixelijtexts(pixel_map_dim_x/2, pixel_map_dim_y/2, "Particle", 255, 255, 255, "", 50, 0, 0);
The first line of code sets the color of the pixel at the center of the screen to white, effectively creating a single white particle at that position. All other pixels remain black, indicating no particle is present.
The second line of code sets the primary text of the particle to "Particle" and its size to 50. In Particle Mode, the particle size is determined by the red component of the secondary text. The empty string ("") is used for the secondary text here.
This code results in a white particle of size "50" at the center of the screen with the text "Particle". The rest of the pixel map remains black, indicating the absence of any other particles.
To create additional particles, you can follow these steps:
setpixelmapdims
function. At the start of the program, all pixel colors are reset to black so you don't need to manually reset the screen.setpixelijcolor(x, y, r, g, b)
function to add a particle at the specified coordinates (x, y) with the desired color (r, g, b).setpixelijtexts
function. This component represents the particle's size and ranges from 0 to 255. The primary text in this function sets the particle's primary text, the secondary text is settable too. Just its color will be the same as primary text's color.By following these steps, you can create and customize particles on the pixel map, allowing for cool visualizations and effects.