UNPKG

finalytics

Version:

Node.js wrapper for finalytics Rust library using FFI

640 lines (576 loc) 17.5 kB
import { Ticker, TickerBuilder } from './ticker.js'; import { Tickers, TickersBuilder } from './tickers.js'; import { Portfolio, PortfolioBuilder } from './portfolio.js'; import { Screener } from './screener.js'; import { Chart } from './utils.js' import Polars from 'nodejs-polars'; import fs from 'fs'; import { fileURLToPath } from 'url'; // Export all classes for use in other modules export { TickerBuilder, TickersBuilder, PortfolioBuilder, Ticker, Tickers, Portfolio, Screener, Chart, }; // Test all methods of the Ticker class async function testTicker() { console.log('=== Testing Ticker ==='); let ticker; try { ticker = await new TickerBuilder() .symbol('AAPL') .startDate('2023-01-01') .endDate('2023-12-31') .interval('1d') .benchmarkSymbol('^GSPC') .confidenceLevel(0.95) .riskFreeRate(0.02) .build(); } catch (err) { console.error('Error creating Ticker:', err.message); return; } try { const quote = await ticker.getQuote(); console.log('getQuote:', quote); } catch (err) { console.error('Error in getQuote:', err.message); } try { const summary = await ticker.getSummaryStats(); console.log('getSummaryStats:', summary); } catch (err) { console.error('Error in getSummaryStats:', err.message); } try { const history = await ticker.getPriceHistory(); console.log('getPriceHistory:', history); } catch (err) { console.error('Error in getPriceHistory:', err.message); } try { const options = await ticker.getOptionsChain(); console.log('getOptionsChain:', options); } catch (err) { console.error('Error in getOptionsChain:', err.message); } try { const news = await ticker.getNews(); console.log('getNews:', news); } catch (err) { console.error('Error in getNews:', err.message); } try { const income = await ticker.getIncomeStatement('quarterly', true); console.log('getIncomeStatement:', income); } catch (err) { console.error('Error in getIncomeStatement:', err.message); } try { const balance = await ticker.getBalanceSheet('quarterly', true); console.log('getBalanceSheet:', balance); } catch (err) { console.error('Error in getBalanceSheet:', err.message); } try { const cashflow = await ticker.getCashflowStatement('quarterly', true); console.log('getCashflowStatement:', cashflow); } catch (err) { console.error('Error in getCashflowStatement:', err.message); } try { const ratios = await ticker.getFinancialRatios('quarterly'); console.log('getFinancialRatios:', ratios); } catch (err) { console.error('Error in getFinancialRatios:', err.message); } try { const volSurface = await ticker.volatilitySurface(); console.log('volatilitySurface:', volSurface); } catch (err) { console.error('Error in volatilitySurface:', err.message); } try { const perfStats = await ticker.performanceStats(); console.log('performanceStats:', perfStats); } catch (err) { console.error('Error in performanceStats:', err.message); } try { const perfChart = await ticker.performanceChart(0, 0); console.log('performanceChart: Opening in browser...'); await perfChart.show(); } catch (err) { console.error('Error in performanceChart:', err.message); } try { const candleChart = await ticker.candlestickChart(0, 0); console.log('candlestickChart: Opening in browser...'); await candleChart.show(); } catch (err) { console.error('Error in candlestickChart:', err.message); } try { const optChart = await ticker.optionsChart('surface', 0, 0); console.log('optionsChart: Opening in browser...'); await optChart.show(); } catch (err) { console.error('Error in optionsChart:', err.message); } try { const newsChart = await ticker.newsSentimentChart(0, 0); console.log('newsSentimentChart: Opening in browser...'); await newsChart.show(); } catch (err) { console.error('Error in newsSentimentChart:', err.message); } try { const report = await ticker.report('performance'); console.log('report: Opening in browser...'); await report.show(); } catch (err) { console.error('Error in report:', err.message); } ticker.free(); } // Test all methods of the Tickers class async function testTickers() { console.log('=== Testing Tickers ==='); let tickers; try { tickers = await new TickersBuilder() .symbols(['AAPL', 'MSFT']) .startDate('2023-01-01') .endDate('2023-12-31') .interval('1d') .benchmarkSymbol('^GSPC') .confidenceLevel(0.95) .riskFreeRate(0.02) .build(); } catch (err) { console.error('Error creating Tickers:', err.message); return; } try { const summary = await tickers.getSummaryStats(); console.log('getSummaryStats:', summary); } catch (err) { console.error('Error in getSummaryStats:', err.message); } try { const history = await tickers.getPriceHistory(); console.log('getPriceHistory:', history); } catch (err) { console.error('Error in getPriceHistory:', err.message); } try { const options = await tickers.getOptionsChain(); console.log('getOptionsChain:', options); } catch (err) { console.error('Error in getOptionsChain:', err.message); } try { const income = await tickers.getIncomeStatement('quarterly', true); console.log('getIncomeStatement:', income); } catch (err) { console.error('Error in getIncomeStatement:', err.message); } try { const balance = await tickers.getBalanceSheet('quarterly', true); console.log('getBalanceSheet:', balance); } catch (err) { console.error('Error in getBalanceSheet:', err.message); } try { const cashflow = await tickers.getCashflowStatement('quarterly', true); console.log('getCashflowStatement:', cashflow); } catch (err) { console.error('Error in getCashflowStatement:', err.message); } try { const ratios = await tickers.getFinancialRatios('quarterly'); console.log('getFinancialRatios:', ratios); } catch (err) { console.error('Error in getFinancialRatios:', err.message); } try { const returns = await tickers.returns(); console.log('returns:', returns); } catch (err) { console.error('Error in returns:', err.message); } try { const perfStats = await tickers.performanceStats(); console.log('performanceStats:', perfStats); } catch (err) { console.error('Error in performanceStats:', err.message); } try { const retChart = await tickers.returnsChart(0, 0); console.log('returnsChart: Opening in browser...'); await retChart.show(); } catch (err) { console.error('Error in returnsChart:', err.message); } try { const retMatrix = await tickers.returnsMatrix(0, 0); console.log('returnsMatrix: Opening in browser...'); await retMatrix.show(); } catch (err) { console.error('Error in returnsMatrix:', err.message); } try { const report = await tickers.report('performance'); console.log('report: Opening in browser...'); await report.show(); } catch (err) { console.error('Error in report:', err.message); } try { const ticker = await tickers.getTicker('AAPL'); console.log('getTicker: Successfully retrieved ticker for AAPL'); ticker.free(); } catch (err) { console.error('Error in getTicker:', err.message); } try { const portfolio = await tickers.optimize('max_sharpe', '{}', '{}', '{}'); console.log('optimize: Successfully created portfolio'); portfolio.free(); } catch (err) { console.error('Error in optimize:', err.message); } tickers.free(); } // Test all methods of the Portfolio class async function testPortfolio() { console.log('=== Testing Portfolio ==='); let portfolio; try { portfolio = await new PortfolioBuilder() .tickerSymbols(['AAPL', 'MSFT', 'NVDA', 'BTC-USD']) .benchmarkSymbol('^GSPC') .startDate('2023-01-01') .endDate('2023-12-31') .interval('1d') .confidenceLevel(0.95) .riskFreeRate(0.02) .objectiveFunction('max_sharpe') .assetConstraints('{}') .categoricalConstraints('{}') .weights('{}') .build(); } catch (err) { console.error('Error creating Portfolio:', err.message); return; } try { const results = await portfolio.optimizationResults(); console.log('optimizationResults:', results); } catch (err) { console.error('Error in optimizationResults:', err.message); } try { const optChart = await portfolio.optimizationChart(0, 0); console.log('optimizationChart: Opening in browser...'); await optChart.show(); } catch (err) { console.error('Error in optimizationChart:', err.message); } try { const perfChart = await portfolio.performanceChart(0, 0); console.log('performanceChart: Opening in browser...'); await perfChart.show(); } catch (err) { console.error('Error in performanceChart:', err.message); } try { const assetChart = await portfolio.assetReturnsChart(0, 0); console.log('assetReturnsChart: Opening in browser...'); await assetChart.show(); } catch (err) { console.error('Error in assetReturnsChart:', err.message); } try { const retMatrix = await portfolio.returnsMatrix(0, 0); console.log('returnsMatrix: Opening in browser...'); await retMatrix.show(); } catch (err) { console.error('Error in returnsMatrix:', err.message); } try { const report = await portfolio.report('performance'); console.log('report: Opening in browser...'); await report.show(); } catch (err) { console.error('Error in report:', err.message); } portfolio.free(); } // Test all methods of the Screener class async function testScreener() { console.log('=== Testing Screener ==='); let screener; try { screener = await Screener.new( 'EQUITY', [ JSON.stringify({ operator: 'eq', operands: ['exchange', 'NMS'] }), JSON.stringify({ operator: 'gte', operands: ['intradaymarketcap', 10000000000] }), ], 'intradaymarketcap', true, 0, 10 ); } catch (err) { console.error('Error creating Screener:', err.message); return; } try { const symbols = await screener.symbols(); console.log('symbols:', symbols); } catch (err) { console.error('Error in symbols:', err.message); } try { const overview = await screener.overview(); console.log('overview:', overview); } catch (err) { console.error('Error in overview:', err.message); } try { const metrics = await screener.metrics(); console.log('Screener Metrics:', metrics); } catch (err) { console.error('Error in Screener Metrics:', err.message); } screener.free(); } // Test Ticker, Tickers, and Portfolio with CSV data async function ioTest() { console.log('=== IO Test ==='); const files = { nvda: '../examples/datasets/nvda.csv', goog: '../examples/datasets/goog.csv', aapl: '../examples/datasets/aapl.csv', msft: '../examples/datasets/msft.csv', btcusd: '../examples/datasets/btcusd.csv', gspc: '../examples/datasets/gspc.csv', }; const dataFrames = {}; for (const [name, path] of Object.entries(files)) { try { const csvData = fs.readFileSync(path, 'utf8'); dataFrames[name] = Polars.readCSV(csvData); } catch (err) { console.error(`Error reading ${path}:`, err.message); return; } } console.log('--- Testing Ticker ---'); let ticker; try { ticker = await new TickerBuilder() .symbol('AAPL') .startDate('2023-01-01') .endDate('2023-12-31') .interval('1d') .benchmarkSymbol('^GSPC') .confidenceLevel(0.95) .riskFreeRate(0.02) .tickerData(dataFrames['aapl']) .benchmarkData(dataFrames['gspc']) .build(); const report = await ticker.report('performance'); console.log('Ticker report: Opening in browser...'); await report.show(); } catch (err) { console.error('Error in Ticker report:', err.message); } finally { if (ticker) ticker.free(); } console.log('--- Testing Tickers ---'); let tickers; try { const tickersData = [ dataFrames['nvda'], dataFrames['goog'], dataFrames['aapl'], dataFrames['msft'], dataFrames['btcusd'], ]; tickers = await new TickersBuilder() .symbols(['NVDA', 'GOOG', 'AAPL', 'MSFT', 'BTC-USD']) .startDate('2023-01-01') .endDate('2023-12-31') .interval('1d') .benchmarkSymbol('^GSPC') .confidenceLevel(0.95) .riskFreeRate(0.02) .tickersData(tickersData) .benchmarkData(dataFrames['gspc']) .build(); const report = await tickers.report('full'); console.log('Tickers report: Opening in browser...'); await report.show(); } catch (err) { console.error('Error in Tickers report:', err.message); } finally { if (tickers) tickers.free(); } console.log('--- Testing Portfolio ---'); let portfolio; try { const tickersData = [ dataFrames['nvda'], dataFrames['goog'], dataFrames['aapl'], dataFrames['msft'], dataFrames['btcusd'], ]; const assetConstraints = JSON.stringify([ [0.1, 0.5], [0.1, 0.5], [0.1, 0.5], [0.1, 0.5], [0.1, 0.5], ]); const categoricalConstraints = JSON.stringify([ { name: 'AssetClass', category_per_symbol: ['EQUITY', 'EQUITY', 'EQUITY', 'EQUITY', 'CRYPTO'], weight_per_category: [ ['EQUITY', 0.0, 0.8], ['CRYPTO', 0.0, 0.2], ], }, ]); portfolio = await new PortfolioBuilder() .tickerSymbols(['NVDA', 'GOOG', 'AAPL', 'MSFT', 'BTC-USD']) .benchmarkSymbol('^GSPC') .startDate('2023-01-01') .endDate('2023-12-31') .interval('1d') .confidenceLevel(0.95) .riskFreeRate(0.02) .objectiveFunction('max_sharpe') .assetConstraints(assetConstraints) .categoricalConstraints(categoricalConstraints) .weights('{}') .tickersData(tickersData) .benchmarkData(dataFrames['gspc']) .build(); const perfStats = await portfolio.performanceStats() console.log(perfStats) const report = await portfolio.report('perfomance'); console.log('Portfolio report: Opening in browser...'); await report.show(); } catch (err) { console.error('Error in Portfolio report:', err.message); } finally { if (portfolio) portfolio.free(); } } // README example demonstrating a practical workflow async function readmeExample() { console.log('=== README Example ==='); let screener; try { screener = await Screener.new( 'EQUITY', [ JSON.stringify({ operator: 'eq', operands: ['exchange', 'NMS'] }), JSON.stringify({ operator: 'gte', operands: ['intradaymarketcap', 10000000000] }), ], 'intradaymarketcap', true, 0, 10 ); } catch (err) { console.error('Error creating Screener:', err.message); return; } let symbols; try { symbols = await screener.symbols(); console.log('Screened Symbols:', symbols); } catch (err) { console.error('Failed to get symbols:', err.message); screener.free(); return; } let tickers; try { tickers = await new TickersBuilder() .symbols(symbols) .startDate('2023-01-01') .endDate('2024-12-31') .interval('1d') .benchmarkSymbol('^GSPC') .confidenceLevel(0.95) .riskFreeRate(0.02) .build(); } catch (err) { console.error('Failed to create Tickers:', err.message); screener.free(); return; } if (symbols.length > 0) { let ticker; try { ticker = await tickers.getTicker(symbols[0]); for (const reportType of ['performance', 'financials', 'options', 'news']) { try { const report = await ticker.report(reportType); console.log(`Ticker ${reportType} report: Opening in browser...`); await report.show(); } catch (err) { console.error(`Failed to get ${reportType} report:`, err.message); } } } catch (err) { console.error('Failed to get Ticker:', err.message); } finally { if (ticker) ticker.free(); } } try { const tickersReport = await tickers.report('performance'); console.log('Tickers report: Opening in browser...'); await tickersReport.show(); } catch (err) { console.error('Failed to get Tickers report:', err.message); } let portfolio; try { portfolio = await tickers.optimize('max_sharpe', '{}', '{}', '{}'); const portfolioReport = await portfolio.report('performance'); console.log('Portfolio report: Opening in browser...'); await portfolioReport.show(); } catch (err) { console.error('Failed to optimize portfolio or get report:', err.message); } finally { if (portfolio) portfolio.free(); } tickers.free(); screener.free(); } // Run all tests async function main() { await testTicker(); await testTickers(); await testPortfolio(); await testScreener(); await ioTest(); await readmeExample(); } if (fileURLToPath(import.meta.url) === process.argv[1]) { main().catch(err => console.error('Main error:', err.message)); }