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,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' };
},
});
}
}