Ease of Movement
Install and import#
npm install fintech-algorithmsimport { easeOfMovement } from "fintech-algorithms/technical-indicators/volume-indicators/ease-of-movement";Signature#
easeOfMovement(input)Divides the typical-price change by a box ratio built from scaled volume over the bar range, then smooths that raw reading with a simple moving average.
Parameters#
| Name | Type | Notes |
|---|---|---|
input | TopicInput | bars needs timestamp, high, low, close and volume. From parameters this topic reads volume_scale (default 1000000, a finite number of at least 0.000001) and period (default 14, an integer of at least 2). |
Returns#
TopicResult
series holds raw, the unsmoothed reading, and value, its simple moving average over period. latest carries the last element of each. raw is null on the first bar and on any bar whose high equals its low or whose volume is 0; value needs a full window of non-null raw, so it starts later than raw. Both warm-ups are described below.
Warm-up#
The first 1 bar for `raw`; `period` bars for `value` (index 14 with the defaults) positions are null. ready_at is 1, driven by raw. Because a null inside the window restarts the average, any flat or zero-volume bar pushes value out by a further period bars.
Errors#
- When
volume_scaleis below 0.000001 or not a finite number — throws Error - When
periodis not an integer of at least 2 — throws Error - When a bar carries a negative
volume— throws Error
Complexity: time O(n),
space O(n).
Worked example#
executed Captured by running this function on the input its own test provides. Real output of real code — but not asserted against a published figure.
Input#
{
"bars": [
{
"timestamp": "2024-01-02",
"basis": "synthetic-unadjusted",
"open": 100,
"high": 101.45,
"low": 98.695,
"close": 100,
"volume": 750000,
"benchmark": 200
},
{
"timestamp": "2024-01-03",
"basis": "synthetic-unadjusted",
"open": 101.49111452,
"high": 103.38381693,
"low": 100.05480022,
"close": 101.78791214,
"volume": 795117,
"benchmark": 200.56326135
},
{
"timestamp": "2024-01-04",
"basis": "synthetic-unadjusted",
"open": 102.45519048,
"high": 104.6701838,
"low": 100.91147007,
"close": 102.9549389,
"volume": 840234,
"benchmark": 201.11020913
}
],
"parameters": {}
}Call#
easeOfMovement(input)Returns#
object with 9 fields: topic_id, title, state, ready, ready_at, series, latest, parameters, …
{
"topic_id": "D07-F05-A12",
"title": "Ease of Movement",
"state": "calculated",
"ready": true,
"ready_at": 1,
"series": {
"raw": [
null,
7.09182670339273,
4.935760375263474,
1.1777185136470167,
-1.4745208573506723,
-1.699726591438122
],
"value": [null, null, null, null, null, null]
},
"latest": {
"raw": -3.4562255141040934,
"value": -0.7167616272036208
},
"parameters": {},
"diagnostics": {
"causal": true,
"input_count": 96
}
}Diagrams#
Calculation flow#
Ease of Movement calculation flow
flowchart LR
A["basis-consistent OHLCV observations with venue/session cov"] --> B["Validate order, basis, and finite values"]
B --> C["Apply the selected Ease of Movement convention"]
C --> D["Emit value, readiness, and diagnostics"]
D --> E["Interpret descriptively; test outcomes separately"]
B -->|invalid or insufficient| X["Withhold output with a reason"]
Ease of Movement readiness and evidence states
stateDiagram-v2
[*] --> Waiting
Waiting --> Ready: enough valid causal observations
Waiting --> Rejected: malformed or unsupported input
Ready --> Calculated: selected formula applied
Calculated --> Interpreted: diagnostic and limitation retained
Interpreted --> Ready: next observation arrives
Rejected --> Waiting: corrected input and deterministic reset
How it works#
This page states the contract — how to call it correctly. The article explains the concept: why it works, and where it breaks.
References#
- TA-Lib function groups — see linked primary or authoritative record
- TA-Lib C/C++ API — see linked primary or authoritative record
- TA-Lib maintained source — see linked primary or authoritative record
- Evidence decision
- Level 1 evidence map