# How to write functions

## Rules

1. There are **three** data types mainly concerned.
   1. **Type1 : Number.** Represents a numeric value. In calculation it is handled as a **decimal type**, so that it has a precision up to 12th decimal place.
   2. **Type2 : Time-series** combined by **time and value only.** The array that has only time and value columns. The type of elements in value is number.&#x20;
   3. **Type3 : Time-series** with **more columns** than 2. The array that has multiple columns as number type. Usually, the imported data itself belong to it.&#x20;
2. As a **result** of function, type **2** and **3** are allowed. However, considering the compatibility for visualizing multiple functions in a chart, **2** is advised as a result.
3. Sometimes, time-series data could have **null** as a column's value, which represents **unknown** or **not existing**. If a arithmetics are applied between null and number, it would return null except for + and -.

***

## Arithmetics

You can apply arithmetics such as +(add), -(subtract), \*(multiply), /(divide), %(remainder) and etc, not only with the numbers but **also with the time-series**.

* An arithmetic with a **number** and **the time-series** is applied to every number values in the time-series with the number.
* An arithmetic between two time-series executes calculation with the **values** **at the same time**. Handling on not-matched time is different by the arithmetics.

{% hint style="info" %}
When applying arithmetic between two time-series, **only type 2** time-series are allowed to prevent ambiguity.
{% endhint %}

Arithmetic by **function** is also possible. For example, `R1 + 3` is same as `add(R1+3)`. Moreover, some functions such as `divide` has more option when using function. `divide(R2,5,4)` will perform division on the number values in `R2` by 5 and round it up to the 4th decimal place.

***

## Functions

We support a variety of functions that can be useful to handle the time-series data. Not only the functions derived from the other programming languages like `max`, `exp`, `ifThen`, and `compare`, but also some useful **utility functions** such as `filter`, and `convert` and the **technical indicators** calculated from the market data such as `rsi(relative strength index)`, `mfi(money flow index)`.

See function library for the full list of the functions.

### Utility functions

Unlike numbers time-series could return unexpected result unless the data is well-controlled. To prevent such case, we supports utility functions to refine the data before applying to the other functions.

The followings are **the most used** utils.

#### **filter**

Filter extracts a specific columns **from the type 3** time-series and returns the extracted one as a **type 2** time-series. You can also apply filter by **\_ convention**.&#x20;

<pre><code># 1. It returns type 2 time-series with time, and quote_volume columns from R1.
<strong>filter(R1, quote_volume)
</strong>
# 2. It works same as filter(R1, quote_volume)
<strong>R1_quote_volume
</strong>
# 3. _ convention only works on a data alias
<strong>slide(R1, -2)_quote_volume # ERROR
</strong><strong>filter(slide(R1, -2), quote_volume) # correct
</strong><strong>slide(R1_qoute_volume, -2) # correct
</strong></code></pre>

#### **convert**

Convert manipulates the **interval** of the time-series. Most of the time-series data have their own interval. Candlesticks would have 1 day, 1 hour or 5 minutes interval, and funding histories usually have about 8 hours interval. However, many functions assumes that the data have the same intervals. To meet that requirement, convert has come out.&#x20;

When converting, the values of newly added time are same as the most recent value at that time.

Allowed intervals are **d(day)**, **h(hour)**, and **min(minute).**

It also has a third argument as a **true** or **false**. If true, the filling and removing performs to the current time. Or if false, it performs only to the last time of the original data.

<pre><code># 1. convert R2's interval into 10 minutes
# to the current time.
<strong>convert(R2, 10min, true)
</strong>
# 2. convert R3's interval into 3 days
# and fill/remove the data only to the last time of R3
<strong>convert(R3, 3d, false)
</strong></code></pre>

#### fillInterval

Even if you import a 5 minutes candlestick data, it doesn't mean that the data always has a row for each 5 minutes. It varies by the exchange's policy. For example, there are exchanges that do not create a row at a time when the trade didn't happen. However, some functions might not work in that case. This is when the **fillInterval** is needed.

fillInterval evaluates the interval of the given data, and then fills the omitted time as the **previous values**. If you want to fill the values with **null**, not the previous ones, then you can use **fillIntervalWithNull**.

<pre><code># 1. fill intervals of R2_close.
# In fact, It's recommended to use `convert` if you know the interval.
<strong>fillInterval(R2_close)
</strong>
# 2. fill interval with null of R3, then get the high value of it.
# This could be a good function for visualization.
<strong>filter(fillIntervalWithNull(R3),high)
</strong></code></pre>

#### slide

You may want to calculate the values between the ones of the current and the past. For example, to get the amount of **daily change** of the close price, `(close price of (time A)) - (close price of (time A - 1 day))` is needed. **Slide** came out to resolve such case with the interval data.

Slide function shifts the **time** of the interval data. The first argument of the slide is the **data to shift**, and the second one is a number, the **amount of shifted interval**. If it is positive, then the time  moves to the **future**. On the other hand, it moves to the past if it is negative.

<pre><code># 1. Get the daily change of the close price of R1
# Assume that R1 is a daily candlestick data
<strong>R1_close - slide(R1_close, 1)
</strong><strong>R1_close - (slide(R1_close, 1) * ((R1_close * 0) + 1)) # removing invalid tail value
</strong></code></pre>

### Technical indicators

There are functions that helps you get the **technical indicators** such as `rsi(relative strength index)`, `mfi(money-flow index)`, `trix(triple exponential smoothed moving average)`, and etc, by using the market data easily. For convenience, most of them automatically filter columns even if you insert type 3 data as the argument.&#x20;

On the other hands, some functions like `stochastic(stochastic oscillator)` requires type 3 candlestick data, not a type 2 filtered one.

And if the function uses **volume** data, we recommend you to insert filtered volume data in it. It's because the candlestick data have a lot of volume columns(quote\_volume, buy\_quote\_volume, base\_volume, etc), and this fact causes inconsistent choice of volume at the function's logic.

<pre><code># 1. Those two functions return the same RSI result.
<strong>rsi(R1)
</strong><strong>rsi(R1_close)
</strong>
# 2. It calculates RSI by the high price of R1
<strong>rsi(R1_high)
</strong>
# 3. It returns TRIX of R2
<strong>trix(R2)
</strong>
# 4. However, it returns error, since R2_close does not have `high` and `low` columns.
<strong>trix(R2_close)
</strong></code></pre>

***

## Function failed

Sometimes, the function could fail. If it fails, you would see the error messages of the result of the data becomes empty. Then you have to fix the code and try again.
