UNPKG

@neabyte/candlestick-cli

Version:

Beautiful terminal candlestick charts with real-time trading data. Create stunning ASCII art charts directly in your terminal with support for live market data, custom colors, and professional trading visualization.

1 lines 4.02 kB
import{ChartData}from"../chart/chart-data.js";import{ChartRenderer}from"../chart/chart-renderer.js";import{InfoBar}from"../chart/info-bar.js";import{VolumePane}from"../chart/volume-pane.js";import{YAxis}from"../chart/y-axis.js";import{ChartRenderError,ConfigurationError}from"../types/errors.js";import{validateCandles,validateRGBColor,validateChartDimensions}from"../utils/validation.js";const UNKNOWN_ERROR_MESSAGE="Unknown error",AUTO_RESIZE_INITIAL_DELAY=100;export class Chart{chartData;infoBar;renderer;highlights={};volumePane;yAxis;constructor(t,e={}){try{validateCandles(t);const{title:r="My chart",width:a=0,height:o=0,rendererClass:i=ChartRenderer}=e;if(validateChartDimensions(a,o),r&&"string"!=typeof r)throw new ConfigurationError("Chart title must be a string","title");this.renderer=new i,this.chartData=new ChartData(t,{width:a,height:o}),this.yAxis=new YAxis(this.chartData),this.infoBar=new InfoBar(r),this.volumePane=new VolumePane(Math.floor(this.chartData.height/6))}catch(t){if(t instanceof ChartRenderError||t instanceof ConfigurationError)throw t;const e=t instanceof Error?t.message:"Unknown error";throw new ChartRenderError(`Failed to initialize chart: ${e}`)}}async render(){return await this.renderer.render(this)}async draw(){try{const t=await this.render();void 0!==globalThis.process&&globalThis.process.stdout?(globalThis.process.stdout.write(`${t}\n`),globalThis.process.stdout.write("")):globalThis.console.log(t)}catch(t){const e=t instanceof Error?t.message:"Unknown error";throw new ChartRenderError(`Failed to draw chart: ${e}`)}}setBearColor(t,e,r){try{validateRGBColor(t,e,r),this.renderer.bearishColor=[t,e,r]}catch(t){const e=t instanceof Error?t.message:"Unknown error";throw new ConfigurationError(`Invalid bear color: ${e}`,"bearColor")}}setBullColor(t,e,r){try{validateRGBColor(t,e,r),this.renderer.bullishColor=[t,e,r]}catch(t){const e=t instanceof Error?t.message:"Unknown error";throw new ConfigurationError(`Invalid bull color: ${e}`,"bullColor")}}setHighlight(t,e){e?this.highlights[t]=e:delete this.highlights[t]}setName(t){this.infoBar.name=t}setVolBearColor(t,e,r){this.volumePane.bearishColor=[t,e,r]}setVolBullColor(t,e,r){this.volumePane.bullishColor=[t,e,r]}setVolumePaneEnabled(t){this.volumePane.enabled=t}setVolumePaneHeight(t){this.volumePane.height=t}updateCandles(t,e=!1){e&&this.chartData.resetCandles(),this.chartData.addCandles(t),this.chartData.computeVisibleCandles()}updateSize(t,e){t===this.chartData.terminalSize.width&&e===this.chartData.terminalSize.height||(this.chartData.setSize(t,e),this.chartData.computeVisibleCandles(),this.volumePane.enabled&&this.setVolumePaneHeight(Math.floor(this.chartData.height/6)))}updateSizeFromTerminal(){const t=this.chartData.getTerminalSize();this.updateSize(t.width,t.height)}enableAutoResize(t=1e3){if(void 0===globalThis.process||!globalThis.process.stdout)return void globalThis.console.warn("Auto-resize not available in this environment");this.disableAutoResize();const e=async()=>{try{this.updateSizeFromTerminal(),await this.draw()}catch(t){const e=t instanceof Error?t.message:"Unknown error";globalThis.console.error(`Auto-resize error: ${e}`)}};globalThis.process.stdout.on("resize",e);const r=globalThis.setInterval(e,t);this._cleanupAutoResize=()=>{globalThis.process.stdout.off("resize",e),globalThis.clearInterval(r)},setTimeout(()=>e(),100)}disableAutoResize(){this._cleanupAutoResize&&(this._cleanupAutoResize(),this._cleanupAutoResize=void 0)}setMargins(t=3,e=4,r=2,a=0){try{this.chartData.setMargins(t,e,r,a)}catch(t){const e=t instanceof Error?t.message:"Unknown error";throw new ConfigurationError(`Invalid margins: ${e}`,"margins")}}setScalingMode(t){this.chartData.setScalingMode(t)}setPriceRange(t,e){this.chartData.setPriceRange(t,e)}setTimeRange(t,e){try{this.chartData.setTimeRange(t,e)}catch(t){const e=t instanceof Error?t.message:"Unknown error";throw new ConfigurationError(`Invalid time range: ${e}`,"timeRange")}}fitToData(){this.chartData.fitToData()}_cleanupAutoResize}