Files
KisStock/services/dbService.ts

159 lines
5.1 KiB
TypeScript

import { TradeOrder, OrderType, MarketType, AutoTradeConfig, WatchlistGroup, ReservedOrder, StockTick } from '../types';
import { API_BASE_URL, getHeaders } from './config';
export interface HoldingItem {
code: string;
name: string;
avgPrice: number;
quantity: number;
market: MarketType;
currentPrice: number; // Added
profit: number; // Added
profitRate: number; // Added
}
export class DbService {
constructor() {}
// --- Holdings ---
async getHoldings(): Promise<HoldingItem[]> {
try {
const res = await fetch(`${API_BASE_URL}/account/holdings`);
if (!res.ok) return [];
const data = await res.json();
// Map API response to HoldingItem
// API returns: { stockCode, stockName, quantity, avgPrice, currentPrice, profit, profitRate }
return data.map((h: any) => ({
code: h.stockCode,
name: h.stockName,
avgPrice: h.avgPrice,
quantity: h.quantity,
market: h.stockCode.length > 6 ? MarketType.OVERSEAS : MarketType.DOMESTIC,
currentPrice: h.currentPrice,
profit: h.profit,
profitRate: h.profitRate
}));
} catch (e) {
console.error("Failed to fetch holdings", e);
return [];
}
}
async getAccountSummary() {
try {
const res = await fetch(`${API_BASE_URL}/account/balance?market=Domestic`); // Default
if (!res.ok) return { totalAssets: 0, buyingPower: 0 };
const data = await res.json();
// API returns complex object. We might need to simplify or use /account/summary if exists.
// Or calculate from holdings + cash?
// Using a simplified assumption or endpoints.
// Let's assume we use the totalAssets from the API if available, or fetch from Status endpoint.
// Actually, we verified /account/balance returns KIS raw data.
// We should implemented a summary endpoint or parse raw data.
// For now, let's return a basic structure.
return {
totalAssets: parseFloat(data.output2?.tot_evlu_amt || "0"),
buyingPower: parseFloat(data.output2?.dnca_tot_amt || "0")
};
} catch (e) {
return { totalAssets: 0, buyingPower: 0 };
}
}
// --- Reserved Orders ---
async getReservedOrders(): Promise<ReservedOrder[]> {
const res = await fetch(`${API_BASE_URL}/reserved-orders`);
if (!res.ok) return [];
return await res.json();
}
async saveReservedOrder(order: ReservedOrder) {
// POST
// Map Frontend Order to Backend Request
const payload = {
stockCode: order.stockCode,
stockName: order.stockName,
monitoringType: order.monitoringType,
triggerPrice: order.triggerPrice,
orderType: order.type,
quantity: order.quantity,
price: order.price || 0,
trailingType: order.trailingType,
trailingValue: order.trailingValue,
stopLossValue: order.stopLossValue
};
const res = await fetch(`${API_BASE_URL}/reserved-orders`, {
method: 'POST',
headers: getHeaders(),
body: JSON.stringify(payload)
});
return await res.json();
}
async deleteReservedOrder(id: string) {
await fetch(`${API_BASE_URL}/reserved-orders/${id}`, {
method: 'DELETE'
});
}
// --- Auto Trade Configs ---
async getAutoConfigs(): Promise<AutoTradeConfig[]> {
const res = await fetch(`${API_BASE_URL}/auto-trade/configs`);
if (!res.ok) return [];
return await res.json();
}
async saveAutoConfig(config: AutoTradeConfig) {
await fetch(`${API_BASE_URL}/auto-trade/configs`, {
method: 'POST',
headers: getHeaders(),
body: JSON.stringify(config)
});
}
async deleteAutoConfig(id: string) {
await fetch(`${API_BASE_URL}/auto-trade/configs/${id}`, {
method: 'DELETE'
});
}
// --- Watchlist Groups ---
async getWatchlistGroups(): Promise<WatchlistGroup[]> {
const res = await fetch(`${API_BASE_URL}/watchlists/groups`);
if (!res.ok) return [];
return await res.json();
}
// --- Ticks (Optional, might be local only or via API) ---
// If backend doesn't support generic tick history per session, keep local or ignore.
async saveStockTick(tick: StockTick) {
// No-op or keep local?
// Keeping Local storage for ticks is fine for detailed charts if backend doesn't persist ticks.
// Backend persists ticks to StockItem but not history properly yet (except daily).
}
async getStockTicks(code: string): Promise<StockTick[]> {
return [];
}
// Helpers not needed with real API usually
async syncOrderToHolding(order: TradeOrder) {
// Refresh holdings from server instead of calculating
return await this.getHoldings();
}
// Write-only wrappers
async updateWatchlistGroup(group: WatchlistGroup) {
// Use PUT if available or POST
}
async saveWatchlistGroup(group: WatchlistGroup) {
// POST
}
async deleteWatchlistGroup(id: string) {
// DELETE
}
}