@nandkapadia/lightweight-charts-pro-core
v0.1.1
Published
Framework-agnostic core library for TradingView Lightweight Charts Pro
Downloads
5
Maintainers
Readme
@nandkapadia/lightweight-charts-pro-core
Framework-agnostic TypeScript library for TradingView Lightweight Charts with advanced custom series, primitives, and utilities.
🚀 Features
- Custom Series Plugins: Band, Ribbon, Gradient Ribbon, Signal, and Trend Fill series
- UI Primitives: Legend, Range Switcher, and Trade Rectangle overlays
- Services: Chart coordinate management, layout management, template engine
- Comprehensive Type Definitions: Full TypeScript support with 100% documented APIs
- Framework Agnostic: Use with React, Vue, Streamlit, or vanilla JavaScript
- Tree-Shakeable: Modular exports for optimal bundle sizes
- Production Ready: Zero dependencies (except peer dependency on lightweight-charts)
📦 Installation
npm install @nandkapadia/lightweight-charts-pro-core lightweight-chartsyarn add @nandkapadia/lightweight-charts-pro-core lightweight-chartspnpm add @nandkapadia/lightweight-charts-pro-core lightweight-charts🎯 Quick Start
Basic Usage
import { createChart } from 'lightweight-charts';
import { createBandSeries } from '@nandkapadia/lightweight-charts-pro-core/plugins';
const chart = createChart(document.getElementById('chart'));
const bandSeries = createBandSeries(chart, {
upperLineColor: '#26a69a',
lowerLineColor: '#ef5350',
fillColor: 'rgba(38, 166, 154, 0.2)',
});
bandSeries.setData([
{ time: '2024-01-01', upper: 105, lower: 95 },
{ time: '2024-01-02', upper: 108, lower: 92 },
// ...
]);Using Primitives
import { LegendPrimitive } from '@nandkapadia/lightweight-charts-pro-core/primitives';
const legend = new LegendPrimitive({
text: 'My Series',
position: 'top-left',
});
series.attachPrimitive(legend);Using Services
import { ChartCoordinateService } from '@nandkapadia/lightweight-charts-pro-core/services';
const coordService = ChartCoordinateService.getInstance();
const dimensions = await coordService.getValidatedChartDimensions(chart, container);⏰ Time and Timezone Handling
IMPORTANT: This library does NOT perform any timezone conversions. All time values are treated as opaque.
Philosophy
The library follows a strict "no timezone conversion" policy:
- Backend Responsibility: Your backend/server is responsible for all timezone handling
- Opaque Values: The library treats all time values as-is without modification
- User Control: You have full control over how times are interpreted and displayed
Supported Time Formats
The library accepts and normalizes various time formats WITHOUT conversion:
// Unix timestamp (seconds) - recommended
{ time: 1705312800, value: 100 }
// ISO 8601 string - treated as-is
{ time: '2024-01-15T10:00:00.000Z', value: 100 }
// ISO with timezone offset - preserved
{ time: '2024-01-15T10:00:00.000+05:00', value: 100 }
// BusinessDay format - midnight UTC
{ time: { year: 2024, month: 1, day: 15 }, value: 100 }
// Numeric string
{ time: '1705312800', value: 100 }Best Practices
1. Use Unix Timestamps (Recommended)
// Backend sends Unix timestamps in seconds
const data = [
{ time: 1705312800, value: 100 }, // 2024-01-15 10:00:00 UTC
{ time: 1705316400, value: 105 }, // 2024-01-15 11:00:00 UTC
];2. Backend Handles Timezone Conversion
# Python backend example
from datetime import datetime
import pytz
# User's timezone
user_tz = pytz.timezone('America/New_York')
# Convert to user's timezone BEFORE sending to frontend
dt = datetime(2024, 1, 15, 10, 0, 0, tzinfo=pytz.UTC)
user_dt = dt.astimezone(user_tz)
# Send as Unix timestamp
timestamp = int(user_dt.timestamp()) # Already in user's timezone3. Display Formatting (Optional)
If you need to display times in a specific timezone, use custom formatters:
import { TemplateEngine } from '@nandkapadia/lightweight-charts-pro-core/services';
const engine = TemplateEngine.getInstance();
// Default: ISO 8601 UTC (no conversion)
const result = engine.processTemplate(
'Time: $$time$$',
{ seriesData: { time: 1705312800 } }
);
// Result: "Time: 2024-01-15T10:00:00.000Z"
// Custom: Display in specific timezone
const resultWithTz = engine.processTemplate(
'Time: $$time$$',
{ seriesData: { time: 1705312800 } },
{
timeFormatter: (timestamp) => {
const date = new Date(timestamp * 1000);
return date.toLocaleString('en-US', {
timeZone: 'America/New_York',
dateStyle: 'short',
timeStyle: 'short'
});
}
}
);
// Result: "Time: 1/15/24, 5:00 AM" (EST)What This Library Does
✅ Normalizes different time formats to Unix timestamps (seconds) ✅ Preserves timezone information in ISO strings ✅ Formats times as ISO 8601 UTC by default ✅ Provides optional custom formatters for display ✅ Optimizes time operations with binary search (O(log n))
What This Library Does NOT Do
❌ Does NOT convert times between timezones ❌ Does NOT apply local browser timezone ❌ Does NOT assume any timezone ❌ Does NOT modify your time data
Migration Guide
If you were relying on automatic timezone conversion:
Before (❌ Don't do this):
// Frontend expecting automatic conversion
const data = [
{ time: '2024-01-15T10:00:00Z', value: 100 }
];
// OLD: Would convert to browser timezoneAfter (✅ Do this):
// Backend converts to target timezone
// Python example:
// user_tz = pytz.timezone('America/New_York')
// timestamp = int(dt.astimezone(user_tz).timestamp())
const data = [
{ time: 1705329600, value: 100 } // Already in user's timezone
];Time Utilities
The library provides utilities for working with times:
import {
normalizeTime,
formatTime,
findNearestTimestamp,
createSortedTimeArray
} from '@nandkapadia/lightweight-charts-pro-core/utils';
// Normalize any time format (no conversion)
const timestamp = normalizeTime('2024-01-15T10:00:00.000Z');
// Returns: 1705312800
// Format timestamp (ISO 8601 UTC by default)
const formatted = formatTime(1705312800);
// Returns: "2024-01-15T10:00:00.000Z"
// Find nearest timestamp (O(log n) binary search)
const sorted = createSortedTimeArray([1000, 2000, 3000, 4000, 5000]);
const nearest = findNearestTimestamp(2400, sorted);
// Returns: 2000 (closest match)📚 Documentation
Custom Series
Band Series
Display data with upper and lower bounds (e.g., Bollinger Bands).
import { createBandSeries, BandData } from '@nandkapadia/lightweight-charts-pro-core/plugins';
const data: BandData[] = [
{ time: '2024-01-01', upper: 105, lower: 95 },
{ time: '2024-01-02', upper: 108, lower: 92 },
];
const bandSeries = createBandSeries(chart, {
upperLineColor: '#26a69a',
lowerLineColor: '#ef5350',
fillColor: 'rgba(38, 166, 154, 0.2)',
});
bandSeries.setData(data);Ribbon Series
Multiple moving averages displayed as a ribbon.
import { createRibbonSeries } from '@nandkapadia/lightweight-charts-pro-core/plugins';
const ribbonSeries = createRibbonSeries(chart, {
fillColor: '#2196F3',
opacity: 0.3,
});Signal Series
Binary or numeric signals displayed as colored backgrounds.
import { createSignalSeries } from '@nandkapadia/lightweight-charts-pro-core/plugins';
const signalSeries = createSignalSeries(chart, {
signalColor: '#4CAF50',
neutralColor: 'transparent',
alertColor: '#f44336',
});
signalSeries.setData([
{ time: '2024-01-01', value: 1 }, // Buy signal
{ time: '2024-01-02', value: 0 }, // Neutral
{ time: '2024-01-03', value: -1 }, // Sell signal
]);Unified Series Factory
Descriptor-based series creation with consistent API:
import { SeriesFactory } from '@nandkapadia/lightweight-charts-pro-core/series';
const factory = new SeriesFactory();
// Create any series type
const series = factory.createSeries(chart, {
type: 'band',
data: bandData,
options: {
upperLineColor: '#26a69a',
lowerLineColor: '#ef5350',
},
});
// Get available series types
const types = factory.getAvailableSeriesTypes();
// ['line', 'area', 'candlestick', 'bar', 'histogram', 'baseline', 'band', 'ribbon', ...]
// Check if custom series
const isCustom = factory.isCustomSeries('band'); // truePrimitives
Legend Primitive
Customizable chart legend with template support:
import { createLegendPrimitive, DefaultLegendConfigs } from '@nandkapadia/lightweight-charts-pro-core/primitives';
const legend = createLegendPrimitive({
...DefaultLegendConfigs.default,
text: 'AAPL',
position: 'top-left',
});
series.attachPrimitive(legend);Range Switcher Primitive
Time range selector buttons:
import { createRangeSwitcherPrimitive } from '@nandkapadia/lightweight-charts-pro-core/primitives';
const rangeSwitcher = createRangeSwitcherPrimitive({
ranges: [
{ label: '1D', range: TimeRange.ONE_DAY },
{ label: '1W', range: TimeRange.ONE_WEEK },
{ label: '1M', range: TimeRange.ONE_MONTH },
],
position: 'bottom-right',
});
chart.attachPrimitive(rangeSwitcher);Services
ChartCoordinateService
Singleton service for chart coordinate management:
import { ChartCoordinateService } from '@nandkapadia/lightweight-charts-pro-core/services';
const service = ChartCoordinateService.getInstance();
// Get validated dimensions
const dimensions = await service.getValidatedChartDimensions(chart, container, {
minWidth: 400,
minHeight: 300,
});
// Get pane coordinates
const paneCoords = service.getPaneCoordinates(chart, 0);TemplateEngine
String template interpolation for dynamic content:
import { TemplateEngine } from '@nandkapadia/lightweight-charts-pro-core/services';
const engine = new TemplateEngine();
const result = engine.process('Price: {{price}}', { price: 123.45 });
// Result: "Price: 123.45"🏗️ Architecture
The library is organized into 6 main modules:
1. Plugins (/plugins)
Custom series and chart plugins:
bandSeriesPlugin- Band series with upper/lower boundsribbonSeriesPlugin- Multi-line ribbon visualizationgradientRibbonSeriesPlugin- Ribbon with gradient coloringsignalSeriesPlugin- Binary/numeric signal visualizationtrendFillSeriesPlugin- Trend-following fill areastooltipPlugin- Interactive chart tooltipsrectanglePlugin- Rectangle overlay plugin
2. Primitives (/primitives)
UI primitive components for chart overlays:
BasePanePrimitive- Base class for pane primitivesBaseSeriesPrimitive- Base class for series primitivesLegendPrimitive- Chart legend componentRangeSwitcherPrimitive- Time range selectorTradeRectanglePrimitive- Trade visualization rectangles
3. Series (/series)
Unified series factory with descriptor pattern:
UnifiedSeriesFactory- Main factory for series creationUnifiedSeriesDescriptor- Descriptor pattern for series configUnifiedPropertyMapper- Property mapping utilities- Built-in and custom series descriptors
4. Services (/services)
Chart management services:
ChartCoordinateService- Coordinate system management (singleton)CornerLayoutManager- UI element positioningPrimitiveEventManager- Event handling for primitivesTemplateEngine- String template interpolationTradeTemplateProcessor- Trade data template processing
5. Utils (/utils)
Shared utility functions:
- Logging:
logger,chartLog,primitiveLog,perfLog - Patterns:
SingletonBase,KeyedSingletonManager - Performance:
throttle,memoize,batchDOMUpdates - Validation:
coordinateValidation,dataValidation - Color:
colorUtils,signalColorUtils
6. Types (/types)
TypeScript type definitions for all modules.
🛠️ Development
Prerequisites
- Node.js 18.x or 20.x
- npm, yarn, or pnpm
Setup
# Clone the repository
git clone https://github.com/nandkapadia/lightweight-charts-pro-frontend.git
cd lightweight-charts-pro-frontend
# Install dependencies
npm install
# Build the library
npm run build
# Run tests
npm test
# Run tests in watch mode
npm run test:watch
# Type check
npm run type-check
# Lint
npm run lint
# Format code
npm run formatBuild Output
The build produces:
- ESM:
dist/index.js(ES modules) - CJS:
dist/index.cjs(CommonJS) - Types:
dist/index.d.ts(TypeScript declarations)
Separate entry points for tree-shaking:
dist/plugins/index.jsdist/primitives/index.jsdist/series/index.jsdist/services/index.jsdist/utils/index.js
📖 API Reference
Exports
// Main entry point
import { ... } from '@nandkapadia/lightweight-charts-pro-core';
// Module-specific imports (tree-shakeable)
import { createBandSeries } from '@nandkapadia/lightweight-charts-pro-core/plugins';
import { LegendPrimitive } from '@nandkapadia/lightweight-charts-pro-core/primitives';
import { SeriesFactory } from '@nandkapadia/lightweight-charts-pro-core/series';
import { ChartCoordinateService } from '@nandkapadia/lightweight-charts-pro-core/services';
import { logger } from '@nandkapadia/lightweight-charts-pro-core/utils';Type Definitions
All exports include comprehensive TypeScript type definitions:
import type {
BandData,
BandSeriesOptions,
RibbonData,
SignalData,
ExtendedChartApi,
ExtendedSeriesApi,
} from '@nandkapadia/lightweight-charts-pro-core';🤝 Contributing
We welcome contributions! Please see CONTRIBUTING.md for details.
Development Workflow
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'feat: add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Code Style
- Follow TypeScript best practices
- Use Google-style JSDoc comments
- Ensure all tests pass
- Maintain 100% type safety
- Run
npm run lintandnpm run formatbefore committing
📄 License
MIT License - see LICENSE file for details.
🙏 Acknowledgments
- Built on top of TradingView Lightweight Charts
- Inspired by the needs of quantitative trading applications
- Community feedback and contributions
📞 Support
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Email: [email protected]
🗺️ Roadmap
- [ ] Additional custom series types
- [ ] More UI primitives (volume profile, heatmaps)
- [ ] Enhanced template engine with more formatters
- [ ] Performance optimizations for large datasets
- [ ] Framework-specific examples (React, Vue, Svelte)
- [ ] Comprehensive documentation site
Made with ❤️ for the trading and financial charting community
