212 lines
No EOL
6.4 KiB
TypeScript
212 lines
No EOL
6.4 KiB
TypeScript
import { describe, it, expect } from 'bun:test';
|
|
import {
|
|
// Common utilities
|
|
createProxyUrl,
|
|
sleep,
|
|
|
|
// Date utilities
|
|
dateUtils,
|
|
|
|
// Generic functions
|
|
extractCloses,
|
|
extractOHLC,
|
|
extractVolumes,
|
|
calculateSMA,
|
|
calculateTypicalPrice,
|
|
calculateTrueRange,
|
|
calculateReturns,
|
|
calculateLogReturns,
|
|
calculateVWAP,
|
|
filterBySymbol,
|
|
filterByTimeRange,
|
|
groupBySymbol,
|
|
convertTimestamps,
|
|
|
|
} from '../src/index';
|
|
|
|
describe('Utility Functions', () => {
|
|
describe('common utilities', () => {
|
|
it('should create proxy URL with auth', () => {
|
|
const proxy = {
|
|
protocol: 'http',
|
|
host: '192.168.1.1',
|
|
port: 8080,
|
|
username: 'user',
|
|
password: 'pass',
|
|
};
|
|
|
|
const url = createProxyUrl(proxy);
|
|
expect(url).toBe('http://user:pass@192.168.1.1:8080');
|
|
});
|
|
|
|
it('should create proxy URL without auth', () => {
|
|
const proxy = {
|
|
protocol: 'socks5',
|
|
host: '192.168.1.1',
|
|
port: 1080,
|
|
};
|
|
|
|
const url = createProxyUrl(proxy);
|
|
expect(url).toBe('socks5://192.168.1.1:1080');
|
|
});
|
|
|
|
it('should sleep for specified milliseconds', async () => {
|
|
const start = Date.now();
|
|
await sleep(100);
|
|
const elapsed = Date.now() - start;
|
|
|
|
expect(elapsed).toBeGreaterThanOrEqual(90);
|
|
expect(elapsed).toBeLessThan(200);
|
|
});
|
|
});
|
|
|
|
describe('date utilities', () => {
|
|
it('should check if date is trading day', () => {
|
|
const monday = new Date('2023-12-25'); // Monday
|
|
const saturday = new Date('2023-12-23'); // Saturday
|
|
const sunday = new Date('2023-12-24'); // Sunday
|
|
|
|
expect(dateUtils.isTradingDay(monday)).toBe(true);
|
|
expect(dateUtils.isTradingDay(saturday)).toBe(false);
|
|
expect(dateUtils.isTradingDay(sunday)).toBe(false);
|
|
});
|
|
|
|
it('should get next trading day', () => {
|
|
const friday = new Date('2023-12-22'); // Friday
|
|
const nextDay = dateUtils.getNextTradingDay(friday);
|
|
|
|
expect(nextDay.getDay()).toBe(1); // Monday
|
|
});
|
|
|
|
it('should get previous trading day', () => {
|
|
const monday = new Date('2023-12-25'); // Monday
|
|
const prevDay = dateUtils.getPreviousTradingDay(monday);
|
|
|
|
expect(prevDay.getDay()).toBe(5); // Friday
|
|
});
|
|
|
|
it('should format date as YYYY-MM-DD', () => {
|
|
const date = new Date('2023-12-25T10:30:00Z');
|
|
const formatted = dateUtils.formatDate(date);
|
|
|
|
expect(formatted).toBe('2023-12-25');
|
|
});
|
|
|
|
it('should parse date from string', () => {
|
|
const date = dateUtils.parseDate('2023-12-25');
|
|
|
|
expect(date.getFullYear()).toBe(2023);
|
|
expect(date.getMonth()).toBe(11); // 0-based
|
|
expect(date.getDate()).toBe(25);
|
|
});
|
|
});
|
|
|
|
describe('generic functions', () => {
|
|
const testData = [
|
|
{ open: 100, high: 105, low: 98, close: 103, volume: 1000 },
|
|
{ open: 103, high: 107, low: 101, close: 105, volume: 1200 },
|
|
{ open: 105, high: 108, low: 104, close: 106, volume: 1100 },
|
|
];
|
|
|
|
it('should extract close prices', () => {
|
|
const closes = extractCloses(testData);
|
|
expect(closes).toEqual([103, 105, 106]);
|
|
});
|
|
|
|
it('should extract OHLC data', () => {
|
|
const ohlc = extractOHLC(testData);
|
|
|
|
expect(ohlc.opens).toEqual([100, 103, 105]);
|
|
expect(ohlc.highs).toEqual([105, 107, 108]);
|
|
expect(ohlc.lows).toEqual([98, 101, 104]);
|
|
expect(ohlc.closes).toEqual([103, 105, 106]);
|
|
});
|
|
|
|
it('should extract volumes', () => {
|
|
const volumes = extractVolumes(testData);
|
|
expect(volumes).toEqual([1000, 1200, 1100]);
|
|
});
|
|
|
|
it('should calculate SMA', () => {
|
|
const sma = calculateSMA(testData, 2);
|
|
expect(sma).toHaveLength(2);
|
|
expect(sma[0]).toBe(104);
|
|
expect(sma[1]).toBe(105.5);
|
|
});
|
|
|
|
it('should calculate typical price', () => {
|
|
const typical = calculateTypicalPrice(testData);
|
|
|
|
expect(typical[0]).toBeCloseTo((105 + 98 + 103) / 3);
|
|
expect(typical[1]).toBeCloseTo((107 + 101 + 105) / 3);
|
|
expect(typical[2]).toBeCloseTo((108 + 104 + 106) / 3);
|
|
});
|
|
|
|
it('should calculate true range', () => {
|
|
const tr = calculateTrueRange(testData);
|
|
|
|
expect(tr).toHaveLength(3);
|
|
expect(tr[0]).toBe(7); // 105 - 98
|
|
});
|
|
|
|
it('should calculate returns', () => {
|
|
const returns = calculateReturns(testData);
|
|
|
|
expect(returns).toHaveLength(2);
|
|
expect(returns[0]).toBeCloseTo((105 - 103) / 103);
|
|
expect(returns[1]).toBeCloseTo((106 - 105) / 105);
|
|
});
|
|
|
|
it('should calculate log returns', () => {
|
|
const logReturns = calculateLogReturns(testData);
|
|
|
|
expect(logReturns).toHaveLength(2);
|
|
expect(logReturns[0]).toBeCloseTo(Math.log(105 / 103));
|
|
expect(logReturns[1]).toBeCloseTo(Math.log(106 / 105));
|
|
});
|
|
|
|
it('should calculate VWAP', () => {
|
|
const vwap = calculateVWAP(testData);
|
|
|
|
expect(vwap).toHaveLength(3);
|
|
expect(vwap[0]).toBeGreaterThan(0);
|
|
});
|
|
});
|
|
|
|
describe('OHLCV data operations', () => {
|
|
const ohlcvData = [
|
|
{ symbol: 'AAPL', open: 100, high: 105, low: 98, close: 103, volume: 1000, timestamp: 1000000 },
|
|
{ symbol: 'GOOGL', open: 200, high: 205, low: 198, close: 203, volume: 2000, timestamp: 1000000 },
|
|
{ symbol: 'AAPL', open: 103, high: 107, low: 101, close: 105, volume: 1200, timestamp: 2000000 },
|
|
];
|
|
|
|
it('should filter by symbol', () => {
|
|
const filtered = filterBySymbol(ohlcvData, 'AAPL');
|
|
|
|
expect(filtered).toHaveLength(2);
|
|
expect(filtered.every(item => item.symbol === 'AAPL')).toBe(true);
|
|
});
|
|
|
|
it('should filter by time range', () => {
|
|
const filtered = filterByTimeRange(ohlcvData, 1500000, 2500000);
|
|
|
|
expect(filtered).toHaveLength(1);
|
|
expect(filtered[0].timestamp).toBe(2000000);
|
|
});
|
|
|
|
it('should group by symbol', () => {
|
|
const grouped = groupBySymbol(ohlcvData);
|
|
|
|
expect(grouped['AAPL']).toHaveLength(2);
|
|
expect(grouped['GOOGL']).toHaveLength(1);
|
|
});
|
|
|
|
it('should convert timestamps to dates', () => {
|
|
const converted = convertTimestamps(ohlcvData);
|
|
|
|
expect(converted[0].date).toBeInstanceOf(Date);
|
|
expect(converted[0].date.getTime()).toBe(1000000);
|
|
});
|
|
});
|
|
|
|
}); |