import {z} from 'zod' export type GetApiRestApiV1AccountsAccountIdPerformanceMetricsArgs = {accountId: string, startDate?: string | undefined, endDate?: string | undefined}; export type GetApiRestApiV1AccountsAccountIdPerformanceMetricsOptions = {baseUrl?: string | undefined, ApiKeyAuth?: string | undefined, fetch?: typeof fetch | undefined}; export const accountTypeDTO = z.object({id: z.number().int(), name: z.string().optional()}); export const periodPerformanceDTO = z.object({label: z.string().optional(), netProfit: z.number().optional()}); export const directionPerformanceDTO = z.object({buyNetProfit: z.number().optional(), buyTrades: z.number().int().optional(), buyWinRate: z.number().optional(), sellNetProfit: z.number().optional(), sellTrades: z.number().int().optional(), sellWinRate: z.number().optional()}); export const scoreBreakdownDTO = z.object({accountBalanceScore: z.number().optional(), accountTypeScore: z.number().optional(), consistencyScore: z.number().optional(), diversificationScore: z.number().optional(), expectancyScore: z.number().optional(), isLiveAccount: z.boolean().optional(), martingalePenalty: z.number().optional(), maxDrawdownScore: z.number().optional(), monthsActiveScore: z.number().optional(), overtradingPenalty: z.number().optional(), profitFactorScore: z.number().optional(), recoveryFactorScore: z.number().optional(), riskRewardScore: z.number().optional(), totalTradesScore: z.number().optional(), uniqueAssetClasses: z.number().int().optional(), uniqueInstruments: z.number().int().optional(), winRateScore: z.number().optional()}); export const symbolAnalyticsDTO = z.object({avgProfitPerTrade: z.number().optional(), netProfit: z.number().optional(), symbol: z.string().optional(), trades: z.number().int().optional(), winRate: z.number().optional()}); export const performanceMetricsDTO = z.object({accountType: accountTypeDTO.optional(), advancedAnalyticsAvailable: z.boolean().optional(), avgCommissionPerTrade: z.number().optional(), avgDrawdown: z.number().optional(), avgHoldingTimeSeconds: z.number().int().optional(), avgLoss: z.number().optional(), avgLotSize: z.number().optional(), avgNetProfitPerTrade: z.number().optional(), avgProfitPerMonth: z.record(z.string(), z.number()).optional(), avgRecoveryTimeHours: z.number().optional(), avgRiskReward: z.number().optional(), avgSwapPerTrade: z.number().optional(), avgWin: z.number().optional(), balanceEquityDivergencePerDay: z.record(z.string(), z.number()).optional(), bestDay: periodPerformanceDTO.optional(), bestMonth: periodPerformanceDTO.optional(), bestWeek: periodPerformanceDTO.optional(), breakevenTrades: z.number().int().optional(), broker: z.string().optional(), currency: z.string().optional(), currentEquityDrawdown: z.number().optional(), currentFloatingPnl: z.number().optional(), dailyBalance: z.record(z.string(), z.number()).optional(), dailyBalanceTransactions: z.record(z.string(), z.number()).optional(), dailyEquity: z.record(z.string(), z.number()).optional(), dailyGrowth: z.record(z.string(), z.number()).optional(), dataCollectorEnabled: z.boolean().optional(), dataCollectorHistoryEndAt: z.string().optional(), dataCollectorHistoryStartAt: z.string().optional(), dataCollectorSamples: z.number().int().optional(), directionPerformance: directionPerformanceDTO.optional(), equityCurveSmoothness: z.number().optional(), equityDrawdownPerDay: z.record(z.string(), z.number()).optional(), equityVolatility: z.number().optional(), expectancy: z.number().optional(), firstTradeAt: z.string().optional(), floatingPnlPerDay: z.record(z.string(), z.number()).optional(), grossLoss: z.number().optional(), grossProfit: z.number().optional(), growth: z.number().optional(), intradayMaxDrawdown: z.number().optional(), largestLoss: z.number().optional(), largestWin: z.number().optional(), lastTradeAt: z.string().optional(), longestLossStreak: z.number().int().optional(), longestWinStreak: z.number().int().optional(), losingTrades: z.number().int().optional(), maxCollectorDrawdown: z.number().optional(), maxDrawdown: z.number().optional(), maxFloatingLoss: z.number().optional(), maxFloatingProfit: z.number().optional(), maxLotSize: z.number().optional(), maxRecoveryTimeHours: z.number().optional(), monthsActive: z.number().int().optional(), peakFloatingPnl: z.number().optional(), profitAmountPerMonth: z.record(z.string(), z.number()).optional(), profitFactor: z.number().optional(), profitPerHour: z.record(z.string(), z.number()).optional(), profitPerWeekday: z.record(z.string(), z.number()).optional(), profitPercentagePerMonth: z.record(z.string(), z.number()).optional(), score: z.number().optional(), scoreBreakdown: scoreBreakdownDTO.optional(), symbolAnalytics: z.array(symbolAnalyticsDTO).optional(), timeInDrawdownPercent: z.number().optional(), totalCommissions: z.number().optional(), totalLotSize: z.number().optional(), totalNetProfit: z.number().optional(), totalSwap: z.number().optional(), totalTrades: z.number().int().optional(), tradesByHoldingBucket: z.record(z.string(), z.number().int()).optional(), tradesPerDay: z.record(z.string(), z.number().int()).optional(), tradesPerHour: z.record(z.string(), z.number().int()).optional(), tradesPerSymbol: z.record(z.string(), z.number().int()).optional(), tradesPerWeekday: z.record(z.string(), z.number().int()).optional(), troughFloatingPnl: z.number().optional(), winRate: z.number().optional(), winningTrades: z.number().int().optional(), worstDay: periodPerformanceDTO.optional(), worstMonth: periodPerformanceDTO.optional(), worstWeek: periodPerformanceDTO.optional()}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Get an account performance metrics * * GET /rest/api/v1/accounts/{accountId}/performanceMetrics */ export const getApiRestApiV1AccountsAccountIdPerformanceMetrics = async (args: GetApiRestApiV1AccountsAccountIdPerformanceMetricsArgs, options?: GetApiRestApiV1AccountsAccountIdPerformanceMetricsOptions) => { const {baseUrl = "https://api.metacopier.io", fetch: fetchFn = fetch, ApiKeyAuth} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (args.startDate != null) query.append("startDate", String(args.startDate)) if (args.endDate != null) query.append("endDate", String(args.endDate)) if (ApiKeyAuth !== undefined) headers.set("X-API-KEY", ApiKeyAuth) const url = `${baseUrl.replace(/\/+$/, '')}/rest/api/v1/accounts/${encodeURIComponent(String(args.accountId))}/performanceMetrics${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(performanceMetricsDTO, await res.json()) };