Skip to content

Commit

Permalink
Merge pull request #16 from valamidev/v7
Browse files Browse the repository at this point in the history
V7
  • Loading branch information
valamidev authored Oct 14, 2024
2 parents 6ae6b57 + c599987 commit 75e9ebd
Show file tree
Hide file tree
Showing 14 changed files with 1,109 additions and 528 deletions.
101 changes: 83 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,20 @@

This package allows you to batch OHLCV candlesticks or create them from trade (tick) datasets.

#### Breaking Changes

Version 7.x introduces many breaking changes compared to version 6.x.x.

#### Supported formats:

- OHLCV (CCXT format) `[[time,open,high,low,close,volume]]`
- OHLCV JSON `[{time: number,open: number, high: number, low: number close: number, volume: number}]`
- Trade JSON `[{price: number, quantity: number, time:number}]`
- Tick JSON `[{price: number, quantity: number, time:number}]`
- Trade JSON `[{price: number, quantity: number, time:number, side: number}]`

#### Features:

- Typescript support!
- Typescript
- CCXT support
- No Dependencies
- Performance single loop used
Expand All @@ -34,22 +39,25 @@ npm install candlestick-convert
#### Available functions:

```javascript
import {batchCandleArray, batchCandleArrayCustomInterval, batchCandleJSON, batchTicksToCandle, ticksToTickChart} from "candlestick-convert";
import {batchCandles, batchCandlesWithCustomInterval, batchCandlesJSON, batchTicksToCandle, ticksToTickChart} from "candlestick-convert";

batchCandleArray(candledata: OHLCV[], baseInterval = 60, targetInterval = 300, includeOpenCandle = false)
batchCandles(candledata: OHLCV[], baseInterval = 60, targetInterval = 300, includeOpenCandle = false)
//return OHLCV[]

batchCandleArrayCustomInterval(candleData: OHLCV[], intervalFunction: IntervalFunction, includeOpenCandle = false)
batchCandlesWithCustomInterval(candleData: OHLCV[], intervalFunction: IntervalFunction, includeOpenCandle = false)
//return OHLCV[]

batchCandleJSON(candledata: IOHLCV [], baseInterval = 60, argetInterval = 300)
batchCandlesJSON(candledata: IOHLCV [], baseInterval = 60, argetInterval = 300)
// return IOHLCV[]

batchTicksToCandle(tradedata: TradeTick[], interval = 60, includeOpenCandle = false)
// return IOHLCV[]

ticksToTickChart(tradedata: TradeTick[], numberOfTicks = 5)
// return IOHLCV[]

batchTradeToExtCandle(tradedata: Trade[], interval = 60, includeOpenCandle = false)
// return ExtIOHLCV[]
```

\*\* includeOpenCandle allow non-complete candles in the result, useful for not normalized input data
Expand All @@ -66,17 +74,44 @@ export type IOHLCV = {
volume: number,
};

export type OHLCV = [number, number, number, number, number, number];
// OpenTime, Open, High, Low, Close, Volume
export type ExtIOHLCV = {
time: number,
open: number,
high: number,
low: number,
close: number,
volume: number,
buyVolume: number,
tx: number,
buyTx: number,
};

export type IntervalFunction = (timeStamp: number) => number;
// return the OpenTime for the given timestamp
export const TradeSide = {
BUY: 0,
SELL: 1,
};

export type TradeTick = {
price: number,
quantity: number,
time: number,
price: number;
quantity: number;
time: number;
};

export type Trade = {
price: number;
quantity: number;
time: number;
side: number;
};

export enum OHLCVField {
TIME = 0,
OPEN = 1,
HIGH = 2,
LOW = 3,
CLOSE = 4,
VOLUME = 5,
}
```

## Examples
Expand Down Expand Up @@ -113,10 +148,10 @@ const newFrame = 120; // 120 seconds
const link_btc_2m = batchCandleJSON(link_btc_1m, baseFrame, newFrame);
```

**Tick Chart:**
**Extended Candles from Trades:**

```javascript
import { ticksToTickChart, TradeTick } from "candlestick-convert";
import { batchTradeToExtCandle, Trade } from "candlestick-convert";

const adabnb_trades = [
{
Expand All @@ -140,14 +175,44 @@ const adabnb_trades = [
price: "0.002248",
tradeId: "1221274",
},
// ... more data
];

const filtered_adabnb_trades: TradeTick[] = adabnb_trades.map((trade: any) => ({
const filtered_adabnb_trades: Trade[] = adabnb_trades.map((trade: any) => ({
time: trade.time,
quantity: trade.quantity,
price: trade.price,
side: trade.side === "buy" ? 0 : 1,
}));

const batchSize = 2; // Every TickCandle consist 2 trade
const tickChart = ticksToTickChart(filtered_adabnb_trades, batchSize);
// 1 minute (60 second) Candles
const candles1m = batchTradeToExtCandle(filtered_adabnb_trades, 60);

/* Result:
[
{
time: 1564502580000, // 2019-07-30T16:03:00.000Z
open: 0.00224,
high: 0.00224,
low: 0.00224,
close: 0.00224,
volume: 4458,
buyVolume: 0,
tx: 1,
buyTx: 0,
},
{
time: 1564503120000,
open: 0.00224,
high: 0.002248,
low: 0.002242,
close: 0.002248,
volume: 4949,
buyVolume: 103,
tx: 3,
buyTx: 2,
}
]
```
20 changes: 13 additions & 7 deletions __tests__/Candlestick.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
"use strict";

import CConverter, { IOHLCV, batchCandleArray, OHLCV } from "../src/index";
import {
OHLCV,
batchCandlesWithCustomInterval,
batchCandles,
IOHLCV,
batchCandlesJSON,
} from "../src";

// From Binance
const btc_usdt_1m: OHLCV[] = [
Expand Down Expand Up @@ -50,7 +56,7 @@ test("Candle Convert array CustomInterval", () => {
}
};

let result = CConverter.arrayCustomInterval(
let result = batchCandlesWithCustomInterval(
btc_usdt_1m,
intervalFunction,
true
Expand All @@ -66,15 +72,15 @@ test("Candle Convert array CustomInterval", () => {
});

test("Candle Convert 1m to 5m", () => {
const result = batchCandleArray(btc_usdt_1m, 60, 5 * 60);
const result = batchCandles(btc_usdt_1m, 60, 5 * 60);

expect(result[4]).toEqual(btc_usdt_5m[0]);

expect(result).toHaveLength(6);
});

test("Candle Convert 1m to 5m#withOpenCandles", () => {
const result = batchCandleArray(btc_usdt_1m, 60, 5 * 60, true);
const result = batchCandles(btc_usdt_1m, 60, 5 * 60, true);

expect(result[4]).toEqual(btc_usdt_5m[0]);

Expand All @@ -90,7 +96,7 @@ test("Candle Convert 1m to 5m with missing values", () => {
incompleteArray.splice(13, 1);
incompleteArray.splice(22, 1);

const result = batchCandleArray(incompleteArray, 60, 5 * 60);
const result = batchCandles(incompleteArray, 60, 5 * 60);

expect(incompleteArray.length).toBeLessThan(btc_usdt_1m.length);
expect(result).toHaveLength(6);
Expand Down Expand Up @@ -124,7 +130,7 @@ const candle4h: OHLCV[] = [
];

test("Candle Convert 1Day", () => {
let result = batchCandleArray(candle4h, 4 * 60 * 60, 24 * 60 * 60);
let result = batchCandles(candle4h, 4 * 60 * 60, 24 * 60 * 60);

expect(result[0]).toEqual([
1588204800000, 215.42830423, 227.13385486, 202.0834746, 206.35436145,
Expand Down Expand Up @@ -200,7 +206,7 @@ const link_btc_1m: Array<IOHLCV> = [
];

test("Candle Convert json 2 min", () => {
let result = CConverter.json(link_btc_1m, 60, 120);
let result = batchCandlesJSON(link_btc_1m, 60, 120);

expect(result[0]).toEqual({
close: 0.00024828,
Expand Down
14 changes: 7 additions & 7 deletions __tests__/Tickdata.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use strict";

import Converter, { Trade } from "../src/index";
import { batchTicksToCandle, ticksToTickChart, TradeTick } from "../src";

const adabnb_trades = [
{
Expand Down Expand Up @@ -362,14 +362,14 @@ const adabnb_trades = [
},
];

const filtered_adabnb_trades: Trade[] = adabnb_trades.map((trade: any) => ({
const filtered_adabnb_trades: TradeTick[] = adabnb_trades.map((trade: any) => ({
time: trade.time,
quantity: trade.quantity,
price: trade.price,
}));

test("Tick Chart Convert 5 tick", () => {
let result = Converter.tick_chart(filtered_adabnb_trades, 5);
let result = ticksToTickChart(filtered_adabnb_trades, 5);

expect(result[0]).toEqual({
time: 1564503137490,
Expand All @@ -382,7 +382,7 @@ test("Tick Chart Convert 5 tick", () => {
});

test("Trades convert to Candlestick", () => {
let result = Converter.trade_to_candle(filtered_adabnb_trades, 60);
let result = batchTicksToCandle(filtered_adabnb_trades, 60);

expect(result[0]).toEqual({
time: 1564502580000, // 2019-07-30T16:03:00.000Z
Expand All @@ -400,11 +400,11 @@ test("Trades convert to Candlestick", () => {
});

test("Trades convert to Candlestick, with filter", () => {
let result = Converter.trade_to_candle(
let result = batchTicksToCandle(
filtered_adabnb_trades,
60,
false,
(trade: Trade) => {
(trade: TradeTick) => {
return trade.quantity > 100;
}
);
Expand All @@ -425,7 +425,7 @@ test("Trades convert to Candlestick, with filter", () => {
});

test("Trades convert to Candlestick – including open candle", () => {
let result = Converter.trade_to_candle(filtered_adabnb_trades, 60, true);
let result = batchTicksToCandle(filtered_adabnb_trades, 60, true);

// 27+1 candles, including open (unfinished) candle
expect(result.length).toBe(28);
Expand Down
Loading

0 comments on commit 75e9ebd

Please sign in to comment.