initial setup
This commit is contained in:
commit
232a63dfe8
61 changed files with 4985 additions and 0 deletions
21
packages/config/package.json
Normal file
21
packages/config/package.json
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"name": "@stock-bot/config",
|
||||
"version": "1.0.0",
|
||||
"description": "Shared configuration for the trading bot",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"dev": "tsc --watch",
|
||||
"clean": "rm -rf dist",
|
||||
"test": "echo \"No tests yet\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@stock-bot/shared-types": "workspace:*",
|
||||
"dotenv": "^16.4.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.4.5",
|
||||
"@types/node": "^20.12.12"
|
||||
}
|
||||
}
|
||||
156
packages/config/src/index.ts
Normal file
156
packages/config/src/index.ts
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
import { config } from 'dotenv';
|
||||
import type { DatabaseConfig, BrokerConfig, DataProviderConfig } from '@stock-bot/shared-types';
|
||||
|
||||
// Load environment variables
|
||||
config();
|
||||
|
||||
export const env = {
|
||||
NODE_ENV: process.env.NODE_ENV || 'development',
|
||||
PORT: parseInt(process.env.PORT || '3000'),
|
||||
// Database URLs
|
||||
QUESTDB_URL: process.env.QUESTDB_URL || 'postgresql://admin:quest@localhost:8812/qdb',
|
||||
POSTGRES_URL: process.env.POSTGRES_URL || 'postgresql://postgres:password@localhost:5432/stockbot',
|
||||
DRAGONFLY_URL: process.env.DRAGONFLY_URL || 'redis://localhost:6379',
|
||||
|
||||
// API Keys
|
||||
ALPHA_VANTAGE_API_KEY: process.env.ALPHA_VANTAGE_API_KEY || '',
|
||||
ALPACA_API_KEY: process.env.ALPACA_API_KEY || '',
|
||||
ALPACA_SECRET_KEY: process.env.ALPACA_SECRET_KEY || '',
|
||||
|
||||
// Trading Configuration
|
||||
PAPER_TRADING: process.env.PAPER_TRADING === 'true',
|
||||
MAX_POSITION_SIZE: parseFloat(process.env.MAX_POSITION_SIZE || '0.1'),
|
||||
MAX_DAILY_LOSS: parseFloat(process.env.MAX_DAILY_LOSS || '1000'),
|
||||
|
||||
// Logging
|
||||
LOG_LEVEL: process.env.LOG_LEVEL || 'info',
|
||||
|
||||
// Feature Flags
|
||||
ENABLE_ML_SIGNALS: process.env.ENABLE_ML_SIGNALS === 'true',
|
||||
ENABLE_SENTIMENT_ANALYSIS: process.env.ENABLE_SENTIMENT_ANALYSIS === 'true',
|
||||
} as const;
|
||||
|
||||
export const databaseConfig: DatabaseConfig = {
|
||||
questdb: {
|
||||
host: process.env.QUESTDB_HOST || 'localhost',
|
||||
port: parseInt(process.env.QUESTDB_PORT || '9000'),
|
||||
database: process.env.QUESTDB_DATABASE || 'qdb',
|
||||
},
|
||||
postgres: {
|
||||
host: process.env.POSTGRES_HOST || 'localhost',
|
||||
port: parseInt(process.env.POSTGRES_PORT || '5432'),
|
||||
database: process.env.POSTGRES_DATABASE || 'stockbot',
|
||||
username: process.env.POSTGRES_USERNAME || 'postgres',
|
||||
password: process.env.POSTGRES_PASSWORD || 'password',
|
||||
}, dragonfly: {
|
||||
host: process.env.DRAGONFLY_HOST || 'localhost',
|
||||
port: parseInt(process.env.DRAGONFLY_PORT || '6379'),
|
||||
password: process.env.DRAGONFLY_PASSWORD,
|
||||
},
|
||||
};
|
||||
|
||||
export const brokerConfigs: Record<string, BrokerConfig> = {
|
||||
alpaca: {
|
||||
name: 'Alpaca',
|
||||
apiKey: env.ALPACA_API_KEY,
|
||||
secretKey: env.ALPACA_SECRET_KEY,
|
||||
baseUrl: env.PAPER_TRADING
|
||||
? 'https://paper-api.alpaca.markets'
|
||||
: 'https://api.alpaca.markets',
|
||||
sandbox: env.PAPER_TRADING,
|
||||
},
|
||||
};
|
||||
|
||||
export const dataProviderConfigs: Record<string, DataProviderConfig> = {
|
||||
alphaVantage: {
|
||||
name: 'Alpha Vantage',
|
||||
apiKey: env.ALPHA_VANTAGE_API_KEY,
|
||||
baseUrl: 'https://www.alphavantage.co',
|
||||
rateLimits: {
|
||||
requestsPerSecond: 5,
|
||||
requestsPerDay: 500,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const serviceDefaults = {
|
||||
healthCheckInterval: 30000, // 30 seconds
|
||||
retryAttempts: 3,
|
||||
requestTimeout: 10000, // 10 seconds
|
||||
circuitBreakerThreshold: 5,
|
||||
circuitBreakerTimeout: 60000, // 1 minute
|
||||
};
|
||||
|
||||
export const tradingHours = {
|
||||
market: {
|
||||
open: '09:30',
|
||||
close: '16:00',
|
||||
timezone: 'America/New_York',
|
||||
},
|
||||
premarket: {
|
||||
open: '04:00',
|
||||
close: '09:30',
|
||||
timezone: 'America/New_York',
|
||||
},
|
||||
afterHours: {
|
||||
open: '16:00',
|
||||
close: '20:00',
|
||||
timezone: 'America/New_York',
|
||||
},
|
||||
};
|
||||
|
||||
export const riskDefaults = {
|
||||
maxPositionSize: 0.1, // 10% of portfolio
|
||||
maxDailyLoss: 0.02, // 2% of portfolio
|
||||
maxDrawdown: 0.1, // 10% of portfolio
|
||||
stopLossPercent: 0.05, // 5%
|
||||
takeProfitPercent: 0.15, // 15%
|
||||
};
|
||||
|
||||
// Environment-specific configurations
|
||||
export const getConfig = () => {
|
||||
const base = {
|
||||
env: env.NODE_ENV,
|
||||
port: env.PORT,
|
||||
database: databaseConfig,
|
||||
brokers: brokerConfigs,
|
||||
dataProviders: dataProviderConfigs,
|
||||
services: serviceDefaults,
|
||||
trading: {
|
||||
hours: tradingHours,
|
||||
risk: riskDefaults,
|
||||
paperTrading: env.PAPER_TRADING,
|
||||
},
|
||||
};
|
||||
|
||||
switch (env.NODE_ENV) {
|
||||
case 'development':
|
||||
return {
|
||||
...base,
|
||||
logging: {
|
||||
level: 'debug',
|
||||
console: true,
|
||||
file: false,
|
||||
},
|
||||
cache: {
|
||||
ttl: 300, // 5 minutes
|
||||
},
|
||||
};
|
||||
|
||||
case 'production':
|
||||
return {
|
||||
...base,
|
||||
logging: {
|
||||
level: 'info',
|
||||
console: false,
|
||||
file: true,
|
||||
},
|
||||
cache: {
|
||||
ttl: 60, // 1 minute
|
||||
},
|
||||
};
|
||||
|
||||
default:
|
||||
return base;
|
||||
}
|
||||
};
|
||||
18
packages/config/tsconfig.json
Normal file
18
packages/config/tsconfig.json
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"declaration": true,
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"resolveJsonModule": true
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
23
packages/shared-types/package.json
Normal file
23
packages/shared-types/package.json
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"name": "@stock-bot/shared-types",
|
||||
"version": "1.0.0",
|
||||
"description": "Shared TypeScript definitions for the trading bot",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"dev": "tsc --watch",
|
||||
"clean": "rm -rf dist",
|
||||
"test": "echo \"No tests yet\""
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.4.5"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
204
packages/shared-types/src/index.ts
Normal file
204
packages/shared-types/src/index.ts
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
// Market Data Types
|
||||
export interface OHLCV {
|
||||
symbol: string;
|
||||
timestamp: Date;
|
||||
open: number;
|
||||
high: number;
|
||||
low: number;
|
||||
close: number;
|
||||
volume: number;
|
||||
}
|
||||
|
||||
export interface MarketData {
|
||||
symbol: string;
|
||||
price: number;
|
||||
bid: number;
|
||||
ask: number;
|
||||
volume: number;
|
||||
timestamp: Date;
|
||||
}
|
||||
|
||||
export interface OrderBook {
|
||||
symbol: string;
|
||||
bids: [number, number][]; // [price, size]
|
||||
asks: [number, number][]; // [price, size]
|
||||
timestamp: Date;
|
||||
}
|
||||
|
||||
// Trading Types
|
||||
export type OrderSide = 'BUY' | 'SELL';
|
||||
export type OrderType = 'MARKET' | 'LIMIT' | 'STOP' | 'STOP_LIMIT';
|
||||
export type OrderStatus = 'PENDING' | 'FILLED' | 'PARTIALLY_FILLED' | 'CANCELLED' | 'REJECTED';
|
||||
|
||||
export interface Order {
|
||||
id: string;
|
||||
symbol: string;
|
||||
side: OrderSide;
|
||||
type: OrderType;
|
||||
quantity: number;
|
||||
price?: number;
|
||||
stopPrice?: number;
|
||||
status: OrderStatus;
|
||||
timestamp: Date;
|
||||
strategyId: string;
|
||||
}
|
||||
|
||||
export interface Position {
|
||||
symbol: string;
|
||||
quantity: number;
|
||||
averagePrice: number;
|
||||
marketValue: number;
|
||||
unrealizedPnL: number;
|
||||
timestamp: Date;
|
||||
}
|
||||
|
||||
export interface Portfolio {
|
||||
cash: number;
|
||||
totalValue: number;
|
||||
positions: Position[];
|
||||
dayPnL: number;
|
||||
totalPnL: number;
|
||||
timestamp: Date;
|
||||
}
|
||||
|
||||
// Strategy Types
|
||||
export type SignalType = 'BUY' | 'SELL' | 'HOLD';
|
||||
|
||||
export interface TradingSignal {
|
||||
symbol: string;
|
||||
type: SignalType;
|
||||
strength: number; // 0-1
|
||||
price: number;
|
||||
timestamp: Date;
|
||||
strategyId: string;
|
||||
metadata?: Record<string, any>;
|
||||
}
|
||||
|
||||
export interface Strategy {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
isActive: boolean;
|
||||
riskLimits: RiskLimits;
|
||||
parameters: Record<string, any>;
|
||||
}
|
||||
|
||||
export interface RiskLimits {
|
||||
maxPositionSize: number;
|
||||
maxDailyLoss: number;
|
||||
maxDrawdown: number;
|
||||
allowedSymbols?: string[];
|
||||
}
|
||||
|
||||
// Event Types
|
||||
export interface MarketDataEvent {
|
||||
type: 'MARKET_DATA';
|
||||
data: MarketData;
|
||||
timestamp: Date;
|
||||
}
|
||||
|
||||
export interface OrderEvent {
|
||||
type: 'ORDER_CREATED' | 'ORDER_FILLED' | 'ORDER_CANCELLED';
|
||||
order: Order;
|
||||
timestamp: Date;
|
||||
}
|
||||
|
||||
export interface SignalEvent {
|
||||
type: 'SIGNAL_GENERATED';
|
||||
signal: TradingSignal;
|
||||
timestamp: Date;
|
||||
}
|
||||
|
||||
export type TradingEvent = MarketDataEvent | OrderEvent | SignalEvent;
|
||||
|
||||
// Service Types
|
||||
export interface ServiceConfig {
|
||||
name: string;
|
||||
version: string;
|
||||
environment: 'development' | 'staging' | 'production';
|
||||
port?: number;
|
||||
dependencies?: string[];
|
||||
}
|
||||
|
||||
export interface HealthStatus {
|
||||
service: string;
|
||||
status: 'healthy' | 'unhealthy' | 'degraded';
|
||||
timestamp: Date;
|
||||
details?: Record<string, any>;
|
||||
}
|
||||
|
||||
// API Response Types
|
||||
export interface ApiResponse<T> {
|
||||
success: boolean;
|
||||
data?: T;
|
||||
error?: string;
|
||||
timestamp: Date;
|
||||
}
|
||||
|
||||
export interface PaginatedResponse<T> {
|
||||
data: T[];
|
||||
total: number;
|
||||
page: number;
|
||||
limit: number;
|
||||
hasNext: boolean;
|
||||
}
|
||||
|
||||
// Fundamental Data Types
|
||||
export interface CompanyFundamentals {
|
||||
symbol: string;
|
||||
marketCap: number;
|
||||
peRatio?: number;
|
||||
pbRatio?: number;
|
||||
roe?: number;
|
||||
revenue: number;
|
||||
netIncome: number;
|
||||
lastUpdated: Date;
|
||||
}
|
||||
|
||||
export interface NewsItem {
|
||||
id: string;
|
||||
headline: string;
|
||||
summary: string;
|
||||
sentiment: number; // -1 to 1
|
||||
symbols: string[];
|
||||
source: string;
|
||||
publishedAt: Date;
|
||||
}
|
||||
|
||||
// Configuration Types
|
||||
export interface DatabaseConfig {
|
||||
questdb: {
|
||||
host: string;
|
||||
port: number;
|
||||
database: string;
|
||||
};
|
||||
postgres: {
|
||||
host: string;
|
||||
port: number;
|
||||
database: string;
|
||||
username: string;
|
||||
password: string;
|
||||
}; dragonfly: {
|
||||
host: string;
|
||||
port: number;
|
||||
password?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface BrokerConfig {
|
||||
name: string;
|
||||
apiKey: string;
|
||||
secretKey: string;
|
||||
baseUrl: string;
|
||||
sandbox: boolean;
|
||||
}
|
||||
|
||||
export interface DataProviderConfig {
|
||||
name: string;
|
||||
apiKey: string;
|
||||
baseUrl: string;
|
||||
rateLimits: {
|
||||
requestsPerSecond: number;
|
||||
requestsPerDay: number;
|
||||
};
|
||||
}
|
||||
18
packages/shared-types/tsconfig.json
Normal file
18
packages/shared-types/tsconfig.json
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"declaration": true,
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"resolveJsonModule": true
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue