tradingview-screener-ts
Version:
TypeScript port of TradingView Screener with 100% Python parity - Based on the original Python library by shner-elmo (https://github.com/shner-elmo/TradingView-Screener)
421 lines • 11.9 kB
JavaScript
"use strict";
/**
* Advanced architecture patterns and design implementations
*
* This module implements enterprise-grade architectural patterns including
* Factory, Strategy, Observer, Decorator, and Plugin patterns for maximum
* extensibility and maintainability.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.Architecture = exports.PluginManager = exports.PerformanceObserver = exports.QueryEventManager = exports.DataProcessingContext = exports.CryptoDataProcessor = exports.IndiaStockDataProcessor = exports.StockDataProcessor = exports.IndiaStockQueryBuilder = exports.ForexQueryBuilder = exports.CryptoQueryBuilder = exports.StockQueryBuilder = exports.QueryFactory = void 0;
/**
* Abstract Factory Pattern for creating different types of queries
*/
class QueryFactory {
/**
* Create a query for specific market type
*/
static createMarketQuery(marketType) {
switch (marketType) {
case 'stock':
return new StockQueryBuilder();
case 'crypto':
return new CryptoQueryBuilder();
case 'forex':
return new ForexQueryBuilder();
case 'india':
return new IndiaStockQueryBuilder();
default:
throw new Error(`Unsupported market type: ${marketType}`);
}
}
/**
* Create query from template
*/
static createFromTemplate(template) {
const builder = this.createMarketQuery(template.marketType);
return builder
.setColumns(template.columns)
.setFilters(template.filters)
.setLimit(template.limit);
}
}
exports.QueryFactory = QueryFactory;
/**
* Stock Query Builder Implementation
*/
class StockQueryBuilder {
constructor() {
this.query = {};
}
setColumns(columns) {
this.query.columns =
columns.length > 0 ? columns : ['name', 'close', 'volume', 'market_cap_basic', 'P/E', 'P/B'];
return this;
}
setFilters(filters) {
this.query.filter = filters;
return this;
}
setLimit(limit) {
this.query.range = [0, Math.min(limit, 1000)];
return this;
}
setMarkets(...markets) {
this.query.markets = markets.length > 0 ? markets : ['america'];
return this;
}
build() {
return {
markets: ['america'],
columns: ['name', 'close', 'volume'],
range: [0, 50],
...this.query,
};
}
}
exports.StockQueryBuilder = StockQueryBuilder;
/**
* Crypto Query Builder Implementation
*/
class CryptoQueryBuilder {
constructor() {
this.query = {};
}
setColumns(columns) {
this.query.columns =
columns.length > 0
? columns
: ['name', 'close', 'volume', 'market_cap_calc', 'change', 'change_7d'];
return this;
}
setFilters(filters) {
this.query.filter = filters;
return this;
}
setLimit(limit) {
this.query.range = [0, Math.min(limit, 500)];
return this;
}
setMarkets(..._markets) {
this.query.markets = ['crypto'];
return this;
}
build() {
return {
markets: ['crypto'],
columns: ['name', 'close', 'volume'],
range: [0, 50],
...this.query,
};
}
}
exports.CryptoQueryBuilder = CryptoQueryBuilder;
/**
* Forex Query Builder Implementation
*/
class ForexQueryBuilder {
constructor() {
this.query = {};
}
setColumns(columns) {
this.query.columns =
columns.length > 0 ? columns : ['name', 'close', 'change', 'volatility', 'high', 'low'];
return this;
}
setFilters(filters) {
this.query.filter = filters;
return this;
}
setLimit(limit) {
this.query.range = [0, Math.min(limit, 200)];
return this;
}
setMarkets(..._markets) {
this.query.markets = ['forex'];
return this;
}
build() {
return {
markets: ['forex'],
columns: ['name', 'close', 'change'],
range: [0, 50],
...this.query,
};
}
}
exports.ForexQueryBuilder = ForexQueryBuilder;
/**
* India Stock Query Builder Implementation
*/
class IndiaStockQueryBuilder {
constructor() {
this.query = {};
}
setColumns(columns) {
this.query.columns =
columns.length > 0
? columns
: ['name', 'close', 'volume', 'market_cap_basic', 'P/E', 'debt_to_equity'];
return this;
}
setFilters(filters) {
this.query.filter = filters;
return this;
}
setLimit(limit) {
this.query.range = [0, Math.min(limit, 500)];
return this;
}
setMarkets(..._markets) {
this.query.markets = ['india'];
return this;
}
build() {
return {
markets: ['india'],
columns: ['name', 'close', 'volume'],
range: [0, 50],
...this.query,
};
}
}
exports.IndiaStockQueryBuilder = IndiaStockQueryBuilder;
/**
* Stock Data Processor
*/
class StockDataProcessor {
process(data) {
return {
...data,
data: data.data.map(row => ({
...row,
// Add calculated fields for stocks
market_cap_formatted: this.formatMarketCap(row.market_cap_basic),
pe_category: this.categorizePE(row['P/E']),
})),
};
}
formatMarketCap(marketCap) {
if (marketCap >= 1e12)
return `$${(marketCap / 1e12).toFixed(1)}T`;
if (marketCap >= 1e9)
return `$${(marketCap / 1e9).toFixed(1)}B`;
if (marketCap >= 1e6)
return `$${(marketCap / 1e6).toFixed(1)}M`;
return `$${marketCap.toFixed(0)}`;
}
categorizePE(pe) {
if (pe < 10)
return 'Low';
if (pe < 20)
return 'Moderate';
if (pe < 30)
return 'High';
return 'Very High';
}
}
exports.StockDataProcessor = StockDataProcessor;
/**
* India Stock Data Processor
*/
class IndiaStockDataProcessor {
process(data) {
return {
...data,
data: data.data.map(row => ({
...row,
// Add calculated fields for Indian stocks
market_cap_formatted: this.formatMarketCapINR(row.market_cap_basic),
price_formatted: `₹${row.close?.toFixed(2)}`,
pe_category: this.categorizeIndianPE(row['P/E']),
})),
};
}
formatMarketCapINR(marketCap) {
if (marketCap >= 1e12)
return `₹${(marketCap / 1e12).toFixed(1)}T`;
if (marketCap >= 1e9)
return `₹${(marketCap / 1e9).toFixed(1)}B`;
if (marketCap >= 1e7)
return `₹${(marketCap / 1e7).toFixed(1)}Cr`;
return `₹${(marketCap / 1e5).toFixed(1)}L`;
}
categorizeIndianPE(pe) {
if (pe < 15)
return 'Low';
if (pe < 25)
return 'Moderate';
if (pe < 40)
return 'High';
return 'Very High';
}
}
exports.IndiaStockDataProcessor = IndiaStockDataProcessor;
/**
* Crypto Data Processor
*/
class CryptoDataProcessor {
process(data) {
return {
...data,
data: data.data.map(row => ({
...row,
// Add calculated fields for crypto
volatility_category: this.categorizeVolatility(row.volatility),
price_change_category: this.categorizePriceChange(row.change),
})),
};
}
categorizeVolatility(volatility) {
if (volatility < 0.02)
return 'Low';
if (volatility < 0.05)
return 'Moderate';
if (volatility < 0.1)
return 'High';
return 'Extreme';
}
categorizePriceChange(change) {
if (Math.abs(change) < 2)
return 'Stable';
if (Math.abs(change) < 5)
return 'Moderate';
if (Math.abs(change) < 10)
return 'High';
return 'Extreme';
}
}
exports.CryptoDataProcessor = CryptoDataProcessor;
/**
* Data Processing Context (Strategy Pattern)
*/
class DataProcessingContext {
constructor(processor) {
this.processor = processor;
}
setProcessor(processor) {
this.processor = processor;
}
processData(data) {
return this.processor.process(data);
}
}
exports.DataProcessingContext = DataProcessingContext;
/**
* Query Event Manager
*/
class QueryEventManager {
constructor() {
this.observers = [];
}
addObserver(observer) {
this.observers.push(observer);
}
removeObserver(observer) {
const index = this.observers.indexOf(observer);
if (index > -1) {
this.observers.splice(index, 1);
}
}
notifyQueryStart(query) {
this.observers.forEach(observer => observer.onQueryStart(query));
}
notifyQueryComplete(query, result) {
this.observers.forEach(observer => observer.onQueryComplete(query, result));
}
notifyQueryError(query, error) {
this.observers.forEach(observer => observer.onQueryError(query, error));
}
}
exports.QueryEventManager = QueryEventManager;
/**
* Performance Observer Implementation
*/
class PerformanceObserver {
constructor() {
this.metrics = [];
}
onQueryStart(query) {
this.metrics.push({
query,
startTime: performance.now(),
success: false,
});
}
onQueryComplete(query, _result) {
const metric = this.metrics.find(m => m.query === query && !m.endTime);
if (metric) {
metric.endTime = performance.now();
metric.duration = metric.endTime - metric.startTime;
metric.success = true;
}
}
onQueryError(query, error) {
const metric = this.metrics.find(m => m.query === query && !m.endTime);
if (metric) {
metric.endTime = performance.now();
metric.duration = metric.endTime - metric.startTime;
metric.success = false;
metric.error = error.message;
}
}
getMetrics() {
return [...this.metrics];
}
getAverageQueryTime() {
const completedQueries = this.metrics.filter(m => m.duration);
if (completedQueries.length === 0)
return 0;
const totalTime = completedQueries.reduce((sum, m) => sum + (m.duration || 0), 0);
return totalTime / completedQueries.length;
}
}
exports.PerformanceObserver = PerformanceObserver;
/**
* Plugin Manager
*/
class PluginManager {
constructor() {
this.plugins = new Map();
}
registerPlugin(plugin) {
if (this.plugins.has(plugin.name)) {
throw new Error(`Plugin ${plugin.name} is already registered`);
}
this.plugins.set(plugin.name, plugin);
plugin.initialize();
}
unregisterPlugin(name) {
const plugin = this.plugins.get(name);
if (plugin) {
plugin.destroy();
this.plugins.delete(name);
}
}
getPlugin(name) {
return this.plugins.get(name);
}
getAllPlugins() {
return Array.from(this.plugins.values());
}
}
exports.PluginManager = PluginManager;
/**
* Export architecture components
*/
exports.Architecture = {
QueryFactory,
StockQueryBuilder,
CryptoQueryBuilder,
ForexQueryBuilder,
IndiaStockQueryBuilder,
StockDataProcessor,
IndiaStockDataProcessor,
CryptoDataProcessor,
DataProcessingContext,
QueryEventManager,
PerformanceObserver,
PluginManager,
};
//# sourceMappingURL=architecture.js.map