fix(simple): prefer available user alpaca creds
This commit is contained in:
parent
b690f26a28
commit
dad47fc13d
@ -101,6 +101,28 @@ const computeSimpleProfitTargetPrice = (entryPrice: number, entry: ManualEntryRe
|
|||||||
return Number((entryPrice * (1 + (threshold / 100))).toFixed(4));
|
return Number((entryPrice * (1 + (threshold / 100))).toFixed(4));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const resolvePreferredUserAlpacaCredentials = (user: {
|
||||||
|
ALPACA_API_KEY?: string;
|
||||||
|
ALPACA_SECRET_KEY?: string;
|
||||||
|
REAL_ALPACA_API_KEY?: string;
|
||||||
|
REAL_ALPACA_SECRET_KEY?: string;
|
||||||
|
}): { key: string; secret: string; source: 'paper' | 'live' | 'none' } => {
|
||||||
|
const paperKey = String(user.ALPACA_API_KEY || '').trim();
|
||||||
|
const paperSecret = String(user.ALPACA_SECRET_KEY || '').trim();
|
||||||
|
const liveKey = String(user.REAL_ALPACA_API_KEY || '').trim();
|
||||||
|
const liveSecret = String(user.REAL_ALPACA_SECRET_KEY || '').trim();
|
||||||
|
|
||||||
|
if (config.PAPER_TRADING) {
|
||||||
|
if (paperKey && paperSecret) return { key: paperKey, secret: paperSecret, source: 'paper' };
|
||||||
|
if (liveKey && liveSecret) return { key: liveKey, secret: liveSecret, source: 'live' };
|
||||||
|
} else {
|
||||||
|
if (liveKey && liveSecret) return { key: liveKey, secret: liveSecret, source: 'live' };
|
||||||
|
if (paperKey && paperSecret) return { key: paperKey, secret: paperSecret, source: 'paper' };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { key: '', secret: '', source: 'none' };
|
||||||
|
};
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
logger.info(`Starting ${config.PRODUCT_ID} trading backend...`);
|
logger.info(`Starting ${config.PRODUCT_ID} trading backend...`);
|
||||||
validateConfig();
|
validateConfig();
|
||||||
@ -137,8 +159,9 @@ async function main() {
|
|||||||
|
|
||||||
// --- 1. Identify Primary Key (for Data Fetching) ---
|
// --- 1. Identify Primary Key (for Data Fetching) ---
|
||||||
const isPlaceholder = (val: string) => !val || val === 'your_key' || val === 'your_secret';
|
const isPlaceholder = (val: string) => !val || val === 'your_key' || val === 'your_secret';
|
||||||
const primaryAlpacaKey = (!isPlaceholder(config.ALPACA_API_KEY) ? config.ALPACA_API_KEY : (users.length > 0 ? (config.PAPER_TRADING ? users[0].ALPACA_API_KEY : users[0].REAL_ALPACA_API_KEY) : ''));
|
const preferredPrimaryUserCredentials = users.length > 0 ? resolvePreferredUserAlpacaCredentials(users[0]) : { key: '', secret: '', source: 'none' as const };
|
||||||
const primaryAlpacaSecret = (!isPlaceholder(config.ALPACA_API_SECRET) ? config.ALPACA_API_SECRET : (users.length > 0 ? (config.PAPER_TRADING ? users[0].ALPACA_SECRET_KEY : users[0].REAL_ALPACA_SECRET_KEY) : ''));
|
const primaryAlpacaKey = !isPlaceholder(config.ALPACA_API_KEY) ? config.ALPACA_API_KEY : preferredPrimaryUserCredentials.key;
|
||||||
|
const primaryAlpacaSecret = !isPlaceholder(config.ALPACA_API_SECRET) ? config.ALPACA_API_SECRET : preferredPrimaryUserCredentials.secret;
|
||||||
|
|
||||||
logger.info(`🚨 Bot Initialized for ${config.SYMBOLS.length} Symbols: ${config.SYMBOLS.join(', ')}`);
|
logger.info(`🚨 Bot Initialized for ${config.SYMBOLS.length} Symbols: ${config.SYMBOLS.join(', ')}`);
|
||||||
|
|
||||||
@ -237,14 +260,12 @@ async function main() {
|
|||||||
const ctx = getSimpleWorkerContext(entry);
|
const ctx = getSimpleWorkerContext(entry);
|
||||||
if (!ctx) continue;
|
if (!ctx) continue;
|
||||||
|
|
||||||
const currentPrice = resolveSimpleMarketPrice(entry);
|
|
||||||
if (!(currentPrice && currentPrice > 0)) continue;
|
|
||||||
|
|
||||||
if (shouldArmSimpleBuy(entry)) {
|
if (shouldArmSimpleBuy(entry)) {
|
||||||
|
const currentPrice = resolveSimpleMarketPrice(entry) ?? toPositiveNumber(entry.reference_price);
|
||||||
const triggerPrice = computeSimpleBuyTriggerPrice(entry);
|
const triggerPrice = computeSimpleBuyTriggerPrice(entry);
|
||||||
const desiredQty = toPositiveNumber(entry.quantity);
|
const desiredQty = toPositiveNumber(entry.quantity);
|
||||||
const threshold = toNonNegativeNumber(entry.drop_threshold_for_buy);
|
const threshold = toNonNegativeNumber(entry.drop_threshold_for_buy);
|
||||||
if (!triggerPrice || !desiredQty) continue;
|
if (!triggerPrice || !desiredQty || !(currentPrice && currentPrice > 0)) continue;
|
||||||
if (currentPrice > triggerPrice) continue;
|
if (currentPrice > triggerPrice) continue;
|
||||||
|
|
||||||
const result = await ctx.manualTrader.executeRequest(
|
const result = await ctx.manualTrader.executeRequest(
|
||||||
@ -272,6 +293,9 @@ async function main() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const currentPrice = resolveSimpleMarketPrice(entry);
|
||||||
|
if (!(currentPrice && currentPrice > 0)) continue;
|
||||||
|
|
||||||
if (isSimpleSubmittedStatus(entry.status)) {
|
if (isSimpleSubmittedStatus(entry.status)) {
|
||||||
await bindSimpleBoughtPosition(entry, ctx);
|
await bindSimpleBoughtPosition(entry, ctx);
|
||||||
continue;
|
continue;
|
||||||
@ -458,8 +482,9 @@ async function main() {
|
|||||||
users.push(user);
|
users.push(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
const userKey = config.PAPER_TRADING ? user.ALPACA_API_KEY : user.REAL_ALPACA_API_KEY;
|
const preferredCredentials = resolvePreferredUserAlpacaCredentials(user);
|
||||||
const userSecret = config.PAPER_TRADING ? user.ALPACA_SECRET_KEY : user.REAL_ALPACA_SECRET_KEY;
|
const userKey = preferredCredentials.key;
|
||||||
|
const userSecret = preferredCredentials.secret;
|
||||||
|
|
||||||
if (!userKey || !userSecret) {
|
if (!userKey || !userSecret) {
|
||||||
logger.warn(`⚠️ User ${user.email} missing keys for profile ${profile.name}. Skipping.`);
|
logger.warn(`⚠️ User ${user.email} missing keys for profile ${profile.name}. Skipping.`);
|
||||||
@ -540,8 +565,9 @@ async function main() {
|
|||||||
// Fallback to one-per-user if no profiles table entries exist
|
// Fallback to one-per-user if no profiles table entries exist
|
||||||
logger.info(`👥 No specific profiles found. Falling back to multi-user default...`);
|
logger.info(`👥 No specific profiles found. Falling back to multi-user default...`);
|
||||||
for (const user of users) {
|
for (const user of users) {
|
||||||
const userKey = config.PAPER_TRADING ? user.ALPACA_API_KEY : user.REAL_ALPACA_API_KEY;
|
const preferredCredentials = resolvePreferredUserAlpacaCredentials(user);
|
||||||
const userSecret = config.PAPER_TRADING ? user.ALPACA_SECRET_KEY : user.REAL_ALPACA_SECRET_KEY;
|
const userKey = preferredCredentials.key;
|
||||||
|
const userSecret = preferredCredentials.secret;
|
||||||
|
|
||||||
if (!userKey || !userSecret) continue;
|
if (!userKey || !userSecret) continue;
|
||||||
|
|
||||||
|
|||||||
@ -156,18 +156,20 @@ interface AlpacaCredentials {
|
|||||||
|
|
||||||
async function getUserExecutionAlpacaCredentials(userId: string): Promise<AlpacaCredentials> {
|
async function getUserExecutionAlpacaCredentials(userId: string): Promise<AlpacaCredentials> {
|
||||||
const profile = await getCurrentUserProfile(userId);
|
const profile = await getCurrentUserProfile(userId);
|
||||||
const key = String(config.PAPER_TRADING ? profile.ALPACA_API_KEY || '' : profile.REAL_ALPACA_API_KEY || '').trim();
|
const paperKey = String(profile.ALPACA_API_KEY || '').trim();
|
||||||
const secret = String(config.PAPER_TRADING ? profile.ALPACA_SECRET_KEY || '' : profile.REAL_ALPACA_SECRET_KEY || '').trim();
|
const paperSecret = String(profile.ALPACA_SECRET_KEY || '').trim();
|
||||||
|
const liveKey = String(profile.REAL_ALPACA_API_KEY || '').trim();
|
||||||
|
const liveSecret = String(profile.REAL_ALPACA_SECRET_KEY || '').trim();
|
||||||
|
|
||||||
if (!key || !secret) {
|
if (config.PAPER_TRADING) {
|
||||||
throw new MissingServiceConfigError(
|
if (paperKey && paperSecret) return { key: paperKey, secret: paperSecret };
|
||||||
config.PAPER_TRADING
|
if (liveKey && liveSecret) return { key: liveKey, secret: liveSecret };
|
||||||
? 'User Alpaca paper credentials are not configured'
|
} else {
|
||||||
: 'User Alpaca live credentials are not configured'
|
if (liveKey && liveSecret) return { key: liveKey, secret: liveSecret };
|
||||||
);
|
if (paperKey && paperSecret) return { key: paperKey, secret: paperSecret };
|
||||||
}
|
}
|
||||||
|
|
||||||
return { key, secret };
|
throw new MissingServiceConfigError('User Alpaca credentials are not configured');
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getUserMarketDataAlpacaCredentials(userId: string): Promise<AlpacaCredentials> {
|
async function getUserMarketDataAlpacaCredentials(userId: string): Promise<AlpacaCredentials> {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user