Skip to content

Commit

Permalink
feat: add support for retrieving historical data for Futures and Opti…
Browse files Browse the repository at this point in the history
…ons (#3)
  • Loading branch information
kevinypfan authored and chunkai1312 committed Jul 30, 2024
1 parent df5d392 commit 7b92c67
Show file tree
Hide file tree
Showing 4 changed files with 257 additions and 12 deletions.
11 changes: 10 additions & 1 deletion src/rest/futopt/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import { RestFutOptIntradayQuoteParams, quote } from './intraday/quote';
import { RestFutOptIntradayCandlesParams, candles } from './intraday/candles';
import { RestFutOptIntradayTradesParams, trades } from './intraday/trades';
import { RestFutOptIntradayVolumesParams, volumes } from './intraday/volumes';

import { RestFutOptHistoricalCandlesParams, candles as historicalCandles } from './historical/candles'
import { RestFutOptHistoricalDailyParams, daily } from './historical/daily'



Expand All @@ -23,4 +24,12 @@ export class RestFutOptClient extends RestClient {
volumes: (params: RestFutOptIntradayVolumesParams) => volumes(request, params),
};
}

get historical() {
const request = this.request;
return {
candles: (params: RestFutOptHistoricalCandlesParams) => historicalCandles(request, params),
daily: (params: RestFutOptHistoricalDailyParams) => daily(request, params),
};
}
}
33 changes: 33 additions & 0 deletions src/rest/futopt/historical/candles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { RestClientRequest } from "../../client";

export interface RestFutOptHistoricalCandlesParams {
symbol: string;
contractMonth?: string;
from?: string;
to?: string;
fields?: string;
timeframe?: string;
}

export interface RestFutOptHistoricalCandlesResponse {
symbol: string;
contractMonth?: string;
exchange: string;
timeframe: string;
data: Array<{
date: string;
open: number;
high: number;
low: number;
close: number;
volume: number;
turnover: number;
change: number;
}>;
}


export const candles = (request: RestClientRequest, params: RestFutOptHistoricalCandlesParams) => {
const { symbol, ...options } = params;
return request(`historical/candles/${symbol}`, options) as Promise<RestFutOptHistoricalCandlesResponse>;
}
32 changes: 32 additions & 0 deletions src/rest/futopt/historical/daily.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { RestClientRequest } from "../../client";

export interface RestFutOptHistoricalDailyParams {
symbol: string;
date?: string;
afterhours?: boolean;
}

export interface RestFutOptHistoricalDailyResponse {
date: string;
symbol: string;
exchange: string;
session: string;
data: Array<{
contractMonth: string;
openPrice: number;
highPrice: number;
lowPrice: number;
closePrice: number;
change: number;
changePercent: number;
volume: number;
volumeSpread: number;
openInterest: number;
settlementPrice: number;
}>;
}

export const daily = (request: RestClientRequest, params: RestFutOptHistoricalDailyParams) => {
const { symbol, ...options } = params;
return request(`historical/daily/${symbol}`, options) as Promise<RestFutOptHistoricalDailyResponse>;
}
193 changes: 182 additions & 11 deletions test/rest-client.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -337,53 +337,224 @@ describe('RestClient', () => {
const client = new RestClient({ apiKey: 'api-key' });
const futopt = client.futopt as RestFutOptClient;
expect(futopt.intraday).toBeDefined();
expect(futopt.intraday).toHaveProperty('contracts');
expect(futopt.intraday).toHaveProperty('products');
expect(futopt.intraday).toHaveProperty('tickers');
expect(futopt.intraday).toHaveProperty('ticker');
expect(futopt.intraday).toHaveProperty('quote');
expect(futopt.intraday).toHaveProperty('candles');
expect(futopt.intraday).toHaveProperty('trades');
expect(futopt.intraday).toHaveProperty('volumes');
});

describe('.contracts()', () => {
describe('.products()', () => {
it('should request with api key', async () => {
const client = new RestClient({ apiKey: 'api-key' });
const futopt = client.futopt as RestFutOptClient;
await futopt.intraday.contracts({ type: 'FUTURE' });
await futopt.intraday.products({ type: 'FUTURE' });
expect(fetch).toBeCalledWith(
'https://api.fugle.tw/marketdata/v1.0/futopt/intraday/contracts?type=FUTURE',
'https://api.fugle.tw/marketdata/v1.0/futopt/intraday/products?type=FUTURE',
{ headers: { 'X-API-KEY': 'api-key' } },
);
});

it('should request with bearer token', async () => {
const client = new RestClient({ bearerToken: 'bearer-token' });
const futopt = client.futopt as RestFutOptClient;
await futopt.intraday.contracts({ type: 'FUTURE' });
await futopt.intraday.products({ type: 'FUTURE' });
expect(fetch).toBeCalledWith(
'https://api.fugle.tw/marketdata/v1.0/futopt/intraday/contracts?type=FUTURE',
'https://api.fugle.tw/marketdata/v1.0/futopt/intraday/products?type=FUTURE',
{ headers: { 'Authorization': 'Bearer bearer-token' } },
);
});
});

describe('.products()', () => {
describe('.tickers()', () => {
it('should request with api key', async () => {
const client = new RestClient({ apiKey: 'api-key' });
const futopt = client.futopt as RestFutOptClient;
await futopt.intraday.products({ type: 'FUTURE' });
await futopt.intraday.tickers({ type: 'FUTURE' });
expect(fetch).toBeCalledWith(
'https://api.fugle.tw/marketdata/v1.0/futopt/intraday/products?type=FUTURE',
'https://api.fugle.tw/marketdata/v1.0/futopt/intraday/tickers?type=FUTURE',
{ headers: { 'X-API-KEY': 'api-key' } },
);
});

it('should request with bearer token', async () => {
const client = new RestClient({ bearerToken: 'bearer-token' });
const futopt = client.futopt as RestFutOptClient;
await futopt.intraday.products({ type: 'FUTURE' });
await futopt.intraday.tickers({ type: 'FUTURE' });
expect(fetch).toBeCalledWith(
'https://api.fugle.tw/marketdata/v1.0/futopt/intraday/products?type=FUTURE',
'https://api.fugle.tw/marketdata/v1.0/futopt/intraday/tickers?type=FUTURE',
{ headers: { 'Authorization': 'Bearer bearer-token' } },
);
});
});


describe('.ticker()', () => {
it('should request with api key', async () => {
const client = new RestClient({ apiKey: 'api-key' });
const futopt = client.futopt as RestFutOptClient;
await futopt.intraday.ticker({ symbol: 'TXFH4' });
expect(fetch).toBeCalledWith(
'https://api.fugle.tw/marketdata/v1.0/futopt/intraday/ticker/TXFH4',
{ headers: { 'X-API-KEY': 'api-key' } },
);
});

it('should request with bearer token', async () => {
const client = new RestClient({ bearerToken: 'bearer-token' });
const futopt = client.futopt as RestFutOptClient;
await futopt.intraday.ticker({ symbol: 'TXFH4' });
expect(fetch).toBeCalledWith(
'https://api.fugle.tw/marketdata/v1.0/futopt/intraday/ticker/TXFH4',
{ headers: { 'Authorization': 'Bearer bearer-token' } },
);
});
});

describe('.quote()', () => {
it('should request with api key', async () => {
const client = new RestClient({ apiKey: 'api-key' });
const futopt = client.futopt as RestFutOptClient;
await futopt.intraday.quote({ symbol: 'TXFH4' });
expect(fetch).toBeCalledWith(
'https://api.fugle.tw/marketdata/v1.0/futopt/intraday/quote/TXFH4',
{ headers: { 'X-API-KEY': 'api-key' } },
);
});

it('should request with bearer token', async () => {
const client = new RestClient({ bearerToken: 'bearer-token' });
const futopt = client.futopt as RestFutOptClient;
await futopt.intraday.quote({ symbol: 'TXFH4' });
expect(fetch).toBeCalledWith(
'https://api.fugle.tw/marketdata/v1.0/futopt/intraday/quote/TXFH4',
{ headers: { 'Authorization': 'Bearer bearer-token' } },
);
});
});

describe('.candles()', () => {
it('should request with api key', async () => {
const client = new RestClient({ apiKey: 'api-key' });
const futopt = client.futopt as RestFutOptClient;
await futopt.intraday.candles({ symbol: 'TXFH4' });
expect(fetch).toBeCalledWith(
'https://api.fugle.tw/marketdata/v1.0/futopt/intraday/candles/TXFH4',
{ headers: { 'X-API-KEY': 'api-key' } },
);
});

it('should request with bearer token', async () => {
const client = new RestClient({ bearerToken: 'bearer-token' });
const futopt = client.futopt as RestFutOptClient;
await futopt.intraday.candles({ symbol: 'TXFH4' });
expect(fetch).toBeCalledWith(
'https://api.fugle.tw/marketdata/v1.0/futopt/intraday/candles/TXFH4',
{ headers: { 'Authorization': 'Bearer bearer-token' } },
);
});
});

describe('.trades()', () => {
it('should request with api key', async () => {
const client = new RestClient({ apiKey: 'api-key' });
const futopt = client.futopt as RestFutOptClient;
await futopt.intraday.trades({ symbol: 'TXFH4' });
expect(fetch).toBeCalledWith(
'https://api.fugle.tw/marketdata/v1.0/futopt/intraday/trades/TXFH4',
{ headers: { 'X-API-KEY': 'api-key' } },
);
});

it('should request with bearer token', async () => {
const client = new RestClient({ bearerToken: 'bearer-token' });
const futopt = client.futopt as RestFutOptClient;
await futopt.intraday.trades({ symbol: 'TXFH4' });
expect(fetch).toBeCalledWith(
'https://api.fugle.tw/marketdata/v1.0/futopt/intraday/trades/TXFH4',
{ headers: { 'Authorization': 'Bearer bearer-token' } },
);
});
});

describe('.volumes()', () => {
it('should request with api key', async () => {
const client = new RestClient({ apiKey: 'api-key' });
const futopt = client.futopt as RestFutOptClient;
await futopt.intraday.volumes({ symbol: 'TXFH4' });
expect(fetch).toBeCalledWith(
'https://api.fugle.tw/marketdata/v1.0/futopt/intraday/volumes/TXFH4',
{ headers: { 'X-API-KEY': 'api-key' } },
);
});

it('should request with bearer token', async () => {
const client = new RestClient({ bearerToken: 'bearer-token' });
const futopt = client.futopt as RestFutOptClient;
await futopt.intraday.volumes({ symbol: 'TXFH4' });
expect(fetch).toBeCalledWith(
'https://api.fugle.tw/marketdata/v1.0/futopt/intraday/volumes/TXFH4',
{ headers: { 'Authorization': 'Bearer bearer-token' } },
);
});
});
});

describe('.historical', () => {
it('should contain futopt historical api endpoints', () => {
const client = new RestClient({ apiKey: 'api-key' });
const futopt = client.futopt as RestFutOptClient;
expect(futopt.historical).toBeDefined();
expect(futopt.historical).toHaveProperty('candles');
expect(futopt.historical).toHaveProperty('daily');
});

describe('.candles()', () => {
it('should request with api key', async () => {
const client = new RestClient({ apiKey: 'api-key' });
const futopt = client.futopt as RestFutOptClient;
await futopt.historical.candles({ symbol: 'TXFH4' });
expect(fetch).toBeCalledWith(
'https://api.fugle.tw/marketdata/v1.0/futopt/historical/candles/TXFH4',
{ headers: { 'X-API-KEY': 'api-key' } },
);
});

it('should request with bearer token', async () => {
const client = new RestClient({ bearerToken: 'bearer-token' });
const futopt = client.futopt as RestFutOptClient;
await futopt.historical.candles({ symbol: 'TXFH4' });
expect(fetch).toBeCalledWith(
'https://api.fugle.tw/marketdata/v1.0/futopt/historical/candles/TXFH4',
{ headers: { 'Authorization': 'Bearer bearer-token' } },
);
});
});

describe('.daily()', () => {
it('should request with api key', async () => {
const client = new RestClient({ apiKey: 'api-key' });
const futopt = client.futopt as RestFutOptClient;
await futopt.historical.daily({ symbol: 'TXFH4' });
expect(fetch).toBeCalledWith(
'https://api.fugle.tw/marketdata/v1.0/futopt/historical/daily/TXFH4',
{ headers: { 'X-API-KEY': 'api-key' } },
);
});

it('should request with bearer token', async () => {
const client = new RestClient({ bearerToken: 'bearer-token' });
const futopt = client.futopt as RestFutOptClient;
await futopt.historical.daily({ symbol: 'TXFH4' });
expect(fetch).toBeCalledWith(
'https://api.fugle.tw/marketdata/v1.0/futopt/historical/daily/TXFH4',
{ headers: { 'Authorization': 'Bearer bearer-token' } },
);
});
});
});

});
});

0 comments on commit 7b92c67

Please sign in to comment.