adding data-services

This commit is contained in:
Bojan Kucera 2025-06-03 07:42:48 -04:00
parent e3bfd05b90
commit 405b818c86
139 changed files with 55943 additions and 416 deletions

68
libs/api-client/README.md Normal file
View file

@ -0,0 +1,68 @@
# API Client Library
Type-safe HTTP clients for inter-service communication in the stock-bot project.
## Available Clients
### BacktestClient
Client for interacting with the Backtest Engine service:
```typescript
import { createBacktestClient } from '@stock-bot/api-client';
// Create a client instance
const backtestClient = createBacktestClient('http://localhost:4002');
// Run a backtest
const result = await backtestClient.runBacktest({
strategyId: '123',
startDate: new Date('2023-01-01'),
endDate: new Date('2023-12-31'),
symbols: ['AAPL', 'MSFT', 'GOOG'],
initialCapital: 100000,
parameters: {
riskFactor: 0.5,
positionSizeLimit: 0.1
}
});
```
### StrategyClient
Client for interacting with the Strategy Orchestrator service:
```typescript
import { createStrategyClient } from '@stock-bot/api-client';
// Create a client instance
const strategyClient = createStrategyClient('http://localhost:4001');
// Get a strategy by ID
const strategy = await strategyClient.getStrategy('123');
// Update a strategy
await strategyClient.updateStrategy('123', {
parameters: {
lookbackPeriod: 20,
threshold: 0.02
}
});
// Enable a strategy
await strategyClient.enableStrategy('123');
```
## Creating Custom Clients
Extend the `BaseApiClient` to create clients for other services:
```typescript
import { BaseApiClient } from '@stock-bot/api-client';
class RiskGuardianClient extends BaseApiClient {
async getRiskLimits(portfolioId: string) {
return this.client.get(`/api/risk/limits/${portfolioId}`);
}
}
```

View file

@ -0,0 +1,22 @@
{
"name": "@stock-bot/api-client",
"version": "1.0.0",
"description": "API clients for inter-service communication",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"build": "tsc",
"dev": "tsc --watch",
"clean": "rm -rf dist",
"test": "jest"
},
"dependencies": {
"@stock-bot/shared-types": "workspace:*",
"axios": "^1.6.0"
},
"devDependencies": {
"@types/jest": "^29.5.2",
"jest": "^29.5.0",
"typescript": "^5.4.5"
}
}

View file

@ -0,0 +1,30 @@
import { BaseApiClient } from './BaseApiClient';
import { ApiResponse, BacktestConfig, BacktestResult } from '@stock-bot/shared-types';
/**
* Client for interacting with the Backtest Engine service
*/
export class BacktestClient extends BaseApiClient {
/**
* Run a backtest
*/
async runBacktest(config: BacktestConfig): Promise<ApiResponse<BacktestResult>> {
return this.client.post('/api/backtest/run', config);
}
/**
* Get a backtest by ID
*/
async getBacktest(id: string): Promise<ApiResponse<BacktestResult>> {
return this.client.get(`/api/backtest/${id}`);
}
/**
* List all backtests for a strategy
*/
async listBacktests(strategyId: string): Promise<ApiResponse<BacktestResult[]>> {
return this.client.get(`/api/backtest`, {
params: { strategyId }
});
}
}

View file

@ -0,0 +1,39 @@
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
import { ApiResponse } from '@stock-bot/shared-types';
/**
* Base API client that all service clients extend
*/
export abstract class BaseApiClient {
protected client: AxiosInstance;
constructor(baseURL: string, config?: AxiosRequestConfig) {
this.client = axios.create({
baseURL,
timeout: 10000, // 10 seconds timeout
...config
});
// Add response interceptor for consistent error handling
this.client.interceptors.response.use(
(response) => response.data,
(error) => {
// Format error for consistent error handling
const formattedError = {
status: error.response?.status || 500,
message: error.response?.data?.error || error.message || 'Unknown error',
originalError: error
};
return Promise.reject(formattedError);
}
);
}
/**
* Get the health status of a service
*/
async getHealth(): Promise<ApiResponse<{ status: string }>> {
return this.client.get('/api/health');
}
}

View file

@ -0,0 +1,56 @@
import { BaseApiClient } from './BaseApiClient';
import { ApiResponse, Strategy } from '@stock-bot/shared-types';
/**
* Client for interacting with the Strategy Orchestrator service
*/
export class StrategyClient extends BaseApiClient {
/**
* Get a strategy by ID
*/
async getStrategy(id: string): Promise<ApiResponse<Strategy>> {
return this.client.get(`/api/strategy/${id}`);
}
/**
* List all strategies
*/
async listStrategies(): Promise<ApiResponse<Strategy[]>> {
return this.client.get('/api/strategy');
}
/**
* Create a new strategy
*/
async createStrategy(strategy: Omit<Strategy, 'id'>): Promise<ApiResponse<Strategy>> {
return this.client.post('/api/strategy', strategy);
}
/**
* Update a strategy
*/
async updateStrategy(id: string, strategy: Partial<Strategy>): Promise<ApiResponse<Strategy>> {
return this.client.put(`/api/strategy/${id}`, strategy);
}
/**
* Delete a strategy
*/
async deleteStrategy(id: string): Promise<ApiResponse<void>> {
return this.client.delete(`/api/strategy/${id}`);
}
/**
* Enable a strategy
*/
async enableStrategy(id: string): Promise<ApiResponse<Strategy>> {
return this.client.post(`/api/strategy/${id}/enable`);
}
/**
* Disable a strategy
*/
async disableStrategy(id: string): Promise<ApiResponse<Strategy>> {
return this.client.post(`/api/strategy/${id}/disable`);
}
}

View file

@ -0,0 +1,14 @@
import { BaseApiClient } from './BaseApiClient';
import { BacktestClient } from './BacktestClient';
import { StrategyClient } from './StrategyClient';
export { BaseApiClient, BacktestClient, StrategyClient };
// Factory functions
export function createBacktestClient(baseUrl: string = 'http://localhost:4002'): BacktestClient {
return new BacktestClient(baseUrl);
}
export function createStrategyClient(baseUrl: string = 'http://localhost:4001'): StrategyClient {
return new StrategyClient(baseUrl);
}

View file

@ -0,0 +1,13 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"esModuleInterop": true,
"declaration": true,
"outDir": "dist",
"strict": true,
"sourceMap": true
},
"include": ["src/**/*"]
}