jashdoshi77's picture
fix: eliminate all remaining yfinance/XGBoost/calendar errors on cloud
624c105
import axios from 'axios';
const API_BASE = import.meta.env.DEV ? 'http://localhost:8000/api' : '/api';
const api = axios.create({
baseURL: API_BASE,
headers: { 'Content-Type': 'application/json' },
});
// Attach JWT token to all requests
api.interceptors.request.use((config) => {
const token = localStorage.getItem('qh_token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
// Handle 401 responses
api.interceptors.response.use(
(response) => response,
(error) => {
if (error.response?.status === 401) {
localStorage.removeItem('qh_token');
localStorage.removeItem('qh_user');
if (window.location.pathname !== '/login') {
window.location.href = '/login';
}
}
return Promise.reject(error);
}
);
// ── Auth ─────────────────────────────────────────────────────────────────
export const authAPI = {
register: (data: { email: string; username: string; password: string; full_name?: string }) =>
api.post('/auth/register', data),
login: (data: { email: string; password: string }) =>
api.post('/auth/login', data),
getProfile: () => api.get('/auth/me'),
updateProfile: (data: { full_name?: string; bio?: string }) =>
api.put('/auth/me', data),
};
// ── Market Data ──────────────────────────────────────────────────────────
export const dataAPI = {
getExchanges: () => api.get('/data/exchanges'),
getMarkets: () => api.get('/data/markets'),
getSectors: () => api.get('/data/sectors'),
getPopularTickers: (market: string = 'US') =>
api.get(`/data/popular-tickers?market=${market}`),
getPrices: (ticker: string, period: string = '1y', interval: string = '1d') =>
api.get(`/data/prices/${ticker}?period=${period}&interval=${interval}`),
getCompanyInfo: (ticker: string) => api.get(`/data/company/${ticker}`),
computeFeatures: (data: { ticker: string; features?: string[]; period?: string }) =>
api.post('/data/features', data),
searchNews: (data: { query: string; page_size?: number }) =>
api.post('/data/news', data),
searchTickers: (query: string, limit: number = 15) =>
api.get(`/data/search-tickers?q=${encodeURIComponent(query)}&limit=${limit}`),
};
// ── Quantitative ─────────────────────────────────────────────────────────
export const quantAPI = {
analyzeFactors: (data: { tickers: string[]; factors?: string[]; period?: string }) =>
api.post('/quant/factors/analyze', data),
getFactorDefinitions: () => api.get('/quant/factors/definitions'),
generateSignals: (data: { tickers: string[]; signal_types?: string[]; period?: string }) =>
api.post('/quant/signals/generate', data),
};
// ── Strategies ───────────────────────────────────────────────────────────
export const strategyAPI = {
create: (data: any) => api.post('/strategies/', data),
list: () => api.get('/strategies/'),
get: (id: number) => api.get(`/strategies/${id}`),
update: (id: number, data: any) => api.put(`/strategies/${id}`, data),
delete: (id: number) => api.delete(`/strategies/${id}`),
evaluate: (id: number) => api.post(`/strategies/${id}/evaluate`),
convertGraph: (graph: any) => api.post('/strategies/convert-visual-graph', graph),
};
// ── Portfolios ───────────────────────────────────────────────────────────
export const portfolioAPI = {
create: (data: any) => api.post('/portfolios/', data),
list: () => api.get('/portfolios/'),
get: (id: number) => api.get(`/portfolios/${id}`),
optimize: (data: { tickers: string[]; method?: string; period?: string }) =>
api.post('/portfolios/optimize', data),
};
// ── Risk ─────────────────────────────────────────────────────────────────
export const riskAPI = {
analyze: (data: { tickers: string[]; period?: string; benchmark_ticker?: string }) =>
api.post('/risk/analyze', data),
correlation: (tickers: string[], period: string = '1y') =>
api.post(`/risk/correlation?period=${period}`, tickers),
};
// ── Backtests ────────────────────────────────────────────────────────────
export const backtestAPI = {
run: (data: any) => api.post('/backtests/run', data),
list: () => api.get('/backtests/'),
get: (id: number) => api.get(`/backtests/${id}`),
compare: (strategyIds: number[]) => api.post('/analytics/compare', strategyIds),
};
// ── Marketplace ──────────────────────────────────────────────────────────
export const marketplaceAPI = {
publish: (data: any) => api.post('/marketplace/publish', data),
browse: (params?: { category?: string; sort_by?: string; page?: number; search?: string }) =>
api.get('/marketplace/browse', { params }),
leaderboard: (sort_by: string = 'sharpe_ratio', limit: number = 25) =>
api.get(`/marketplace/leaderboard?sort_by=${sort_by}&limit=${limit}`),
};
// ── AI Research ──────────────────────────────────────────────────────────
export const researchAPI = {
generate: (data: { insight_type: string; tickers?: string[]; context?: string }) =>
api.post('/research/generate', data),
listReports: () => api.get('/research/reports'),
getReport: (id: number) => api.get(`/research/reports/${id}`),
exportPdf: (id: number) => api.get(`/research/reports/${id}/export/pdf`, { responseType: 'blob' }),
exportDocx: (id: number) => api.get(`/research/reports/${id}/export/docx`, { responseType: 'blob' }),
};
// ── Holdings ─────────────────────────────────────────────────────────────
export const holdingsAPI = {
list: () => api.get('/holdings/'),
create: (data: any) => api.post('/holdings/', data),
update: (id: number, data: any) => api.put(`/holdings/${id}`, data),
delete: (id: number) => api.delete(`/holdings/${id}`),
summary: () => api.get('/holdings/summary'),
stressTest: (data: { scenario_id?: string; custom_shock?: number }) =>
api.post('/holdings/stress-test', data),
allStressTests: () => api.get('/holdings/stress-test/all'),
hedgeRecommendations: () => api.get('/holdings/hedge-recommendations'),
optionsHedge: () => api.get('/holdings/options-hedge'),
rebalance: () => api.get('/holdings/rebalance'),
correlation: () => api.get('/holdings/correlation'),
};
// ── Sentiment ────────────────────────────────────────────────────────────
export const sentimentAPI = {
ticker: (ticker: string) => api.get(`/sentiment/ticker/${ticker}`),
marketMood: () => api.get('/sentiment/market-mood'),
multi: (tickers: string[]) => api.post('/sentiment/multi', tickers),
portfolio: () => api.get('/sentiment/portfolio'),
};
// ── Calendar ─────────────────────────────────────────────────────────────
export const calendarAPI = {
events: (days?: number) => api.get(`/calendar/events${days ? `?days=${days}` : ''}`),
publicEvents: (days?: number) => api.get(`/calendar/events/public${days ? `?days=${days}` : ''}`),
};
// ── ML Models ────────────────────────────────────────────────────────────
export const mlAPI = {
predict: (ticker: string, period?: string, horizon?: number) =>
api.post('/ml/predict', { ticker, period: period || '2y', horizon: horizon || 5 }),
regime: (ticker: string, period?: string, history_days?: number) =>
api.post('/ml/regime', { ticker, period: period || '2y', history_days: history_days || 60 }),
clearCache: () => api.post('/ml/clear-cache'),
};
export default api;