running prettier for cleanup

This commit is contained in:
Boki 2025-06-11 10:13:25 -04:00
parent fe7733aeb5
commit d85cd58acd
151 changed files with 29158 additions and 27966 deletions

View file

@ -1,94 +1,94 @@
import { Order, OrderResult, OrderStatus } from '@stock-bot/types';
export interface BrokerInterface {
/**
* Execute an order with the broker
*/
executeOrder(order: Order): Promise<OrderResult>;
/**
* Get order status from broker
*/
getOrderStatus(orderId: string): Promise<OrderStatus>;
/**
* Cancel an order
*/
cancelOrder(orderId: string): Promise<boolean>;
/**
* Get current positions
*/
getPositions(): Promise<Position[]>;
/**
* Get account balance
*/
getAccountBalance(): Promise<AccountBalance>;
}
export interface Position {
symbol: string;
quantity: number;
averagePrice: number;
currentPrice: number;
unrealizedPnL: number;
side: 'long' | 'short';
}
export interface AccountBalance {
totalValue: number;
availableCash: number;
buyingPower: number;
marginUsed: number;
}
export class MockBroker implements BrokerInterface {
private orders: Map<string, OrderResult> = new Map();
private positions: Position[] = [];
async executeOrder(order: Order): Promise<OrderResult> {
const orderId = `mock_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
const result: OrderResult = {
orderId,
symbol: order.symbol,
quantity: order.quantity,
side: order.side,
status: 'filled',
executedPrice: order.price || 100, // Mock price
executedAt: new Date(),
commission: 1.0
};
this.orders.set(orderId, result);
return result;
}
async getOrderStatus(orderId: string): Promise<OrderStatus> {
const order = this.orders.get(orderId);
return order?.status || 'unknown';
}
async cancelOrder(orderId: string): Promise<boolean> {
const order = this.orders.get(orderId);
if (order && order.status === 'pending') {
order.status = 'cancelled';
return true;
}
return false;
}
async getPositions(): Promise<Position[]> {
return this.positions;
}
async getAccountBalance(): Promise<AccountBalance> {
return {
totalValue: 100000,
availableCash: 50000,
buyingPower: 200000,
marginUsed: 0
};
}
}
import { Order, OrderResult, OrderStatus } from '@stock-bot/types';
export interface BrokerInterface {
/**
* Execute an order with the broker
*/
executeOrder(order: Order): Promise<OrderResult>;
/**
* Get order status from broker
*/
getOrderStatus(orderId: string): Promise<OrderStatus>;
/**
* Cancel an order
*/
cancelOrder(orderId: string): Promise<boolean>;
/**
* Get current positions
*/
getPositions(): Promise<Position[]>;
/**
* Get account balance
*/
getAccountBalance(): Promise<AccountBalance>;
}
export interface Position {
symbol: string;
quantity: number;
averagePrice: number;
currentPrice: number;
unrealizedPnL: number;
side: 'long' | 'short';
}
export interface AccountBalance {
totalValue: number;
availableCash: number;
buyingPower: number;
marginUsed: number;
}
export class MockBroker implements BrokerInterface {
private orders: Map<string, OrderResult> = new Map();
private positions: Position[] = [];
async executeOrder(order: Order): Promise<OrderResult> {
const orderId = `mock_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
const result: OrderResult = {
orderId,
symbol: order.symbol,
quantity: order.quantity,
side: order.side,
status: 'filled',
executedPrice: order.price || 100, // Mock price
executedAt: new Date(),
commission: 1.0,
};
this.orders.set(orderId, result);
return result;
}
async getOrderStatus(orderId: string): Promise<OrderStatus> {
const order = this.orders.get(orderId);
return order?.status || 'unknown';
}
async cancelOrder(orderId: string): Promise<boolean> {
const order = this.orders.get(orderId);
if (order && order.status === 'pending') {
order.status = 'cancelled';
return true;
}
return false;
}
async getPositions(): Promise<Position[]> {
return this.positions;
}
async getAccountBalance(): Promise<AccountBalance> {
return {
totalValue: 100000,
availableCash: 50000,
buyingPower: 200000,
marginUsed: 0,
};
}
}

View file

@ -1,57 +1,58 @@
import { Order, OrderResult } from '@stock-bot/types';
import { logger } from '@stock-bot/logger';
import { BrokerInterface } from '../broker/interface.ts';
export class OrderManager {
private broker: BrokerInterface;
private pendingOrders: Map<string, Order> = new Map();
constructor(broker: BrokerInterface) {
this.broker = broker;
}
async executeOrder(order: Order): Promise<OrderResult> {
try {
logger.info(`Executing order: ${order.symbol} ${order.side} ${order.quantity} @ ${order.price}`);
// Add to pending orders
const orderId = `order_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
this.pendingOrders.set(orderId, order);
// Execute with broker
const result = await this.broker.executeOrder(order);
// Remove from pending
this.pendingOrders.delete(orderId);
logger.info(`Order executed successfully: ${result.orderId}`);
return result;
} catch (error) {
logger.error('Order execution failed', error);
throw error;
}
}
async cancelOrder(orderId: string): Promise<boolean> {
try {
const success = await this.broker.cancelOrder(orderId);
if (success) {
this.pendingOrders.delete(orderId);
logger.info(`Order cancelled: ${orderId}`);
}
return success;
} catch (error) {
logger.error('Order cancellation failed', error);
throw error;
}
}
async getOrderStatus(orderId: string) {
return await this.broker.getOrderStatus(orderId);
}
getPendingOrders(): Order[] {
return Array.from(this.pendingOrders.values());
}
}
import { logger } from '@stock-bot/logger';
import { Order, OrderResult } from '@stock-bot/types';
import { BrokerInterface } from '../broker/interface.ts';
export class OrderManager {
private broker: BrokerInterface;
private pendingOrders: Map<string, Order> = new Map();
constructor(broker: BrokerInterface) {
this.broker = broker;
}
async executeOrder(order: Order): Promise<OrderResult> {
try {
logger.info(
`Executing order: ${order.symbol} ${order.side} ${order.quantity} @ ${order.price}`
);
// Add to pending orders
const orderId = `order_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
this.pendingOrders.set(orderId, order);
// Execute with broker
const result = await this.broker.executeOrder(order);
// Remove from pending
this.pendingOrders.delete(orderId);
logger.info(`Order executed successfully: ${result.orderId}`);
return result;
} catch (error) {
logger.error('Order execution failed', error);
throw error;
}
}
async cancelOrder(orderId: string): Promise<boolean> {
try {
const success = await this.broker.cancelOrder(orderId);
if (success) {
this.pendingOrders.delete(orderId);
logger.info(`Order cancelled: ${orderId}`);
}
return success;
} catch (error) {
logger.error('Order cancellation failed', error);
throw error;
}
}
async getOrderStatus(orderId: string) {
return await this.broker.getOrderStatus(orderId);
}
getPendingOrders(): Order[] {
return Array.from(this.pendingOrders.values());
}
}

View file

@ -1,111 +1,113 @@
import { Order } from '@stock-bot/types';
import { getLogger } from '@stock-bot/logger';
export interface RiskRule {
name: string;
validate(order: Order, context: RiskContext): Promise<RiskValidationResult>;
}
export interface RiskContext {
currentPositions: Map<string, number>;
accountBalance: number;
totalExposure: number;
maxPositionSize: number;
maxDailyLoss: number;
}
export interface RiskValidationResult {
isValid: boolean;
reason?: string;
severity: 'info' | 'warning' | 'error';
}
export class RiskManager {
private logger = getLogger('risk-manager');
private rules: RiskRule[] = [];
constructor() {
this.initializeDefaultRules();
}
addRule(rule: RiskRule): void {
this.rules.push(rule);
}
async validateOrder(order: Order, context: RiskContext): Promise<RiskValidationResult> {
for (const rule of this.rules) {
const result = await rule.validate(order, context);
if (!result.isValid) {
logger.warn(`Risk rule violation: ${rule.name}`, {
order,
reason: result.reason
});
return result;
}
}
return { isValid: true, severity: 'info' };
}
private initializeDefaultRules(): void {
// Position size rule
this.addRule({
name: 'MaxPositionSize',
async validate(order: Order, context: RiskContext): Promise<RiskValidationResult> {
const orderValue = order.quantity * (order.price || 0);
if (orderValue > context.maxPositionSize) {
return {
isValid: false,
reason: `Order size ${orderValue} exceeds maximum position size ${context.maxPositionSize}`,
severity: 'error'
};
}
return { isValid: true, severity: 'info' };
}
});
// Balance check rule
this.addRule({
name: 'SufficientBalance',
async validate(order: Order, context: RiskContext): Promise<RiskValidationResult> {
const orderValue = order.quantity * (order.price || 0);
if (order.side === 'buy' && orderValue > context.accountBalance) {
return {
isValid: false,
reason: `Insufficient balance: need ${orderValue}, have ${context.accountBalance}`,
severity: 'error'
};
}
return { isValid: true, severity: 'info' };
}
});
// Concentration risk rule
this.addRule({
name: 'ConcentrationLimit',
async validate(order: Order, context: RiskContext): Promise<RiskValidationResult> {
const currentPosition = context.currentPositions.get(order.symbol) || 0;
const newPosition = order.side === 'buy' ?
currentPosition + order.quantity :
currentPosition - order.quantity;
const positionValue = Math.abs(newPosition) * (order.price || 0);
const concentrationRatio = positionValue / context.accountBalance;
if (concentrationRatio > 0.25) { // 25% max concentration
return {
isValid: false,
reason: `Position concentration ${(concentrationRatio * 100).toFixed(2)}% exceeds 25% limit`,
severity: 'warning'
};
}
return { isValid: true, severity: 'info' };
}
});
}
}
import { getLogger } from '@stock-bot/logger';
import { Order } from '@stock-bot/types';
export interface RiskRule {
name: string;
validate(order: Order, context: RiskContext): Promise<RiskValidationResult>;
}
export interface RiskContext {
currentPositions: Map<string, number>;
accountBalance: number;
totalExposure: number;
maxPositionSize: number;
maxDailyLoss: number;
}
export interface RiskValidationResult {
isValid: boolean;
reason?: string;
severity: 'info' | 'warning' | 'error';
}
export class RiskManager {
private logger = getLogger('risk-manager');
private rules: RiskRule[] = [];
constructor() {
this.initializeDefaultRules();
}
addRule(rule: RiskRule): void {
this.rules.push(rule);
}
async validateOrder(order: Order, context: RiskContext): Promise<RiskValidationResult> {
for (const rule of this.rules) {
const result = await rule.validate(order, context);
if (!result.isValid) {
logger.warn(`Risk rule violation: ${rule.name}`, {
order,
reason: result.reason,
});
return result;
}
}
return { isValid: true, severity: 'info' };
}
private initializeDefaultRules(): void {
// Position size rule
this.addRule({
name: 'MaxPositionSize',
async validate(order: Order, context: RiskContext): Promise<RiskValidationResult> {
const orderValue = order.quantity * (order.price || 0);
if (orderValue > context.maxPositionSize) {
return {
isValid: false,
reason: `Order size ${orderValue} exceeds maximum position size ${context.maxPositionSize}`,
severity: 'error',
};
}
return { isValid: true, severity: 'info' };
},
});
// Balance check rule
this.addRule({
name: 'SufficientBalance',
async validate(order: Order, context: RiskContext): Promise<RiskValidationResult> {
const orderValue = order.quantity * (order.price || 0);
if (order.side === 'buy' && orderValue > context.accountBalance) {
return {
isValid: false,
reason: `Insufficient balance: need ${orderValue}, have ${context.accountBalance}`,
severity: 'error',
};
}
return { isValid: true, severity: 'info' };
},
});
// Concentration risk rule
this.addRule({
name: 'ConcentrationLimit',
async validate(order: Order, context: RiskContext): Promise<RiskValidationResult> {
const currentPosition = context.currentPositions.get(order.symbol) || 0;
const newPosition =
order.side === 'buy'
? currentPosition + order.quantity
: currentPosition - order.quantity;
const positionValue = Math.abs(newPosition) * (order.price || 0);
const concentrationRatio = positionValue / context.accountBalance;
if (concentrationRatio > 0.25) {
// 25% max concentration
return {
isValid: false,
reason: `Position concentration ${(concentrationRatio * 100).toFixed(2)}% exceeds 25% limit`,
severity: 'warning',
};
}
return { isValid: true, severity: 'info' };
},
});
}
}

View file

@ -1,97 +1,101 @@
import { Hono } from 'hono';
import { serve } from '@hono/node-server';
import { getLogger } from '@stock-bot/logger';
import { config } from '@stock-bot/config';
// import { BrokerInterface } from './broker/interface.ts';
// import { OrderManager } from './execution/order-manager.ts';
// import { RiskManager } from './execution/risk-manager.ts';
const app = new Hono();
const logger = getLogger('execution-service');
// Health check endpoint
app.get('/health', (c) => {
return c.json({
status: 'healthy',
service: 'execution-service',
timestamp: new Date().toISOString()
});
});
// Order execution endpoints
app.post('/orders/execute', async (c) => {
try {
const orderRequest = await c.req.json();
logger.info('Received order execution request', orderRequest);
// TODO: Validate order and execute
return c.json({
orderId: `order_${Date.now()}`,
status: 'pending',
message: 'Order submitted for execution'
});
} catch (error) {
logger.error('Order execution failed', error);
return c.json({ error: 'Order execution failed' }, 500);
}
});
app.get('/orders/:orderId/status', async (c) => {
const orderId = c.req.param('orderId');
try {
// TODO: Get order status from broker
return c.json({
orderId,
status: 'filled',
executedAt: new Date().toISOString()
});
} catch (error) {
logger.error('Failed to get order status', error);
return c.json({ error: 'Failed to get order status' }, 500);
}
});
app.post('/orders/:orderId/cancel', async (c) => {
const orderId = c.req.param('orderId');
try {
// TODO: Cancel order with broker
return c.json({
orderId,
status: 'cancelled',
cancelledAt: new Date().toISOString()
});
} catch (error) {
logger.error('Failed to cancel order', error);
return c.json({ error: 'Failed to cancel order' }, 500);
}
});
// Risk management endpoints
app.get('/risk/position/:symbol', async (c) => {
const symbol = c.req.param('symbol');
try {
// TODO: Get position risk metrics
return c.json({
symbol,
position: 100,
exposure: 10000,
risk: 'low'
});
} catch (error) {
logger.error('Failed to get position risk', error);
return c.json({ error: 'Failed to get position risk' }, 500);
}
});
const port = config.EXECUTION_SERVICE_PORT || 3004;
logger.info(`Starting execution service on port ${port}`);
serve({
fetch: app.fetch,
port
}, (info) => {
logger.info(`Execution service is running on port ${info.port}`);
});
import { serve } from '@hono/node-server';
import { Hono } from 'hono';
import { config } from '@stock-bot/config';
import { getLogger } from '@stock-bot/logger';
// import { BrokerInterface } from './broker/interface.ts';
// import { OrderManager } from './execution/order-manager.ts';
// import { RiskManager } from './execution/risk-manager.ts';
const app = new Hono();
const logger = getLogger('execution-service');
// Health check endpoint
app.get('/health', c => {
return c.json({
status: 'healthy',
service: 'execution-service',
timestamp: new Date().toISOString(),
});
});
// Order execution endpoints
app.post('/orders/execute', async c => {
try {
const orderRequest = await c.req.json();
logger.info('Received order execution request', orderRequest);
// TODO: Validate order and execute
return c.json({
orderId: `order_${Date.now()}`,
status: 'pending',
message: 'Order submitted for execution',
});
} catch (error) {
logger.error('Order execution failed', error);
return c.json({ error: 'Order execution failed' }, 500);
}
});
app.get('/orders/:orderId/status', async c => {
const orderId = c.req.param('orderId');
try {
// TODO: Get order status from broker
return c.json({
orderId,
status: 'filled',
executedAt: new Date().toISOString(),
});
} catch (error) {
logger.error('Failed to get order status', error);
return c.json({ error: 'Failed to get order status' }, 500);
}
});
app.post('/orders/:orderId/cancel', async c => {
const orderId = c.req.param('orderId');
try {
// TODO: Cancel order with broker
return c.json({
orderId,
status: 'cancelled',
cancelledAt: new Date().toISOString(),
});
} catch (error) {
logger.error('Failed to cancel order', error);
return c.json({ error: 'Failed to cancel order' }, 500);
}
});
// Risk management endpoints
app.get('/risk/position/:symbol', async c => {
const symbol = c.req.param('symbol');
try {
// TODO: Get position risk metrics
return c.json({
symbol,
position: 100,
exposure: 10000,
risk: 'low',
});
} catch (error) {
logger.error('Failed to get position risk', error);
return c.json({ error: 'Failed to get position risk' }, 500);
}
});
const port = config.EXECUTION_SERVICE_PORT || 3004;
logger.info(`Starting execution service on port ${port}`);
serve(
{
fetch: app.fetch,
port,
},
info => {
logger.info(`Execution service is running on port ${info.port}`);
}
);