work on prices
This commit is contained in:
parent
77bba31456
commit
2f5eaef19c
2 changed files with 46 additions and 32 deletions
|
|
@ -28,26 +28,25 @@ async function getOperationTracker(handler: QMHandler): Promise<QMOperationTrack
|
||||||
export async function updatePrices(
|
export async function updatePrices(
|
||||||
this: QMHandler,
|
this: QMHandler,
|
||||||
input: {
|
input: {
|
||||||
symbol: string;
|
|
||||||
symbolId: number;
|
|
||||||
qmSearchCode: string;
|
qmSearchCode: string;
|
||||||
|
lastRecordDate?: Date;
|
||||||
},
|
},
|
||||||
_context?: ExecutionContext
|
_context?: ExecutionContext
|
||||||
): Promise<{
|
): Promise<{
|
||||||
success: boolean;
|
success: boolean;
|
||||||
symbol: string;
|
qmSearchCode: string;
|
||||||
message: string;
|
message: string;
|
||||||
data?: any;
|
data?: any;
|
||||||
}> {
|
}> {
|
||||||
const { symbol, symbolId, qmSearchCode } = input;
|
const { qmSearchCode, lastRecordDate } = input;
|
||||||
|
|
||||||
this.logger.info('Fetching daily prices', { symbol, symbolId });
|
this.logger.info(`Fetching daily prices ${qmSearchCode}`, { qmSearchCode });
|
||||||
|
|
||||||
const sessionManager = QMSessionManager.getInstance();
|
const sessionManager = QMSessionManager.getInstance();
|
||||||
sessionManager.initialize(this.cache, this.logger);
|
sessionManager.initialize(this.cache, this.logger);
|
||||||
|
|
||||||
// Get a session - you'll need to add the appropriate session ID for prices
|
// Get a session - you'll need to add the appropriate session ID for prices
|
||||||
const sessionId = QM_SESSION_IDS.LOOKUP; // TODO: Update with correct session ID
|
const sessionId = QM_SESSION_IDS.PRICES;
|
||||||
const session = await sessionManager.getSession(sessionId);
|
const session = await sessionManager.getSession(sessionId);
|
||||||
|
|
||||||
if (!session || !session.uuid) {
|
if (!session || !session.uuid) {
|
||||||
|
|
@ -57,15 +56,20 @@ export async function updatePrices(
|
||||||
try {
|
try {
|
||||||
// Build API request for daily prices
|
// Build API request for daily prices
|
||||||
const searchParams = new URLSearchParams({
|
const searchParams = new URLSearchParams({
|
||||||
symbol: symbol,
|
zeroTradeDays: 'false',
|
||||||
symbolId: symbolId.toString(),
|
start: lastRecordDate?.toISOString().split('T')[0] ?? '1960-01-01',
|
||||||
qmodTool: 'DailyPrices',
|
interval: '1',
|
||||||
webmasterId: '500',
|
marketSession: 'mkt',
|
||||||
days: '30' // Get last 30 days
|
freq: 'day',
|
||||||
|
adjusted: 'false',
|
||||||
|
adjustmentType: 'none',
|
||||||
|
unadjusted: 'true',
|
||||||
|
datatype: 'eod',
|
||||||
|
symbol: qmSearchCode,
|
||||||
});
|
});
|
||||||
|
// https://app.quotemedia.com/datatool/getEnhancedChartData.json?zeroTradeDays=false&start=2025-06-22&interval=1&marketSession=mkt&freq=day&adjusted=true&adjustmentType=none&unadjusted=false&datatype=int&symbol=AAPL
|
||||||
// TODO: Update with correct prices endpoint
|
// TODO: Update with correct prices endpoint
|
||||||
const apiUrl = `${QM_CONFIG.BASE_URL}/datatool/prices.json?${searchParams.toString()}`;
|
const apiUrl = `${QM_CONFIG.PRICES_URL}?${searchParams.toString()}`;
|
||||||
|
|
||||||
const response = await fetch(apiUrl, {
|
const response = await fetch(apiUrl, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
|
|
@ -77,31 +81,40 @@ export async function updatePrices(
|
||||||
throw new Error(`QM API request failed: ${response.status} ${response.statusText}`);
|
throw new Error(`QM API request failed: ${response.status} ${response.statusText}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const priceData = await response.json();
|
const responseData = await response.json();
|
||||||
|
|
||||||
// Update session success stats
|
// Update session success stats
|
||||||
await sessionManager.incrementSuccessfulCalls(sessionId, session.uuid);
|
await sessionManager.incrementSuccessfulCalls(sessionId, session.uuid);
|
||||||
|
|
||||||
|
const priceData = responseData.results?.history[0].eoddata || [];
|
||||||
|
|
||||||
|
if(!priceData || priceData.length === 0) {
|
||||||
|
this.logger.warn(`No price data found for symbol ${qmSearchCode}`);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
qmSearchCode,
|
||||||
|
message: `No price data found for symbol ${qmSearchCode}`
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Process and store price data
|
// Process and store price data
|
||||||
if (priceData && priceData.length > 0) {
|
if (priceData && priceData.length > 0) {
|
||||||
// Store prices in a separate collection
|
// Store prices in a separate collection
|
||||||
const processedPrices = priceData.map((price: any) => ({
|
const processedPrices = priceData.map((price: any) => ({
|
||||||
...price,
|
...price,
|
||||||
symbol,
|
qmSearchCode,
|
||||||
symbolId,
|
dateTime: new Date(price.date),
|
||||||
date: new Date(price.date),
|
|
||||||
updated_at: new Date()
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
await this.mongodb.batchUpsert(
|
await this.mongodb.batchUpsert(
|
||||||
'qmPrices',
|
'qmPrices',
|
||||||
processedPrices,
|
processedPrices,
|
||||||
['symbol', 'date'] // Unique keys
|
['qmSearchCode', 'date'] // Unique keys
|
||||||
);
|
);
|
||||||
|
|
||||||
// Find the latest price date
|
// Find the latest price date
|
||||||
const latestDate = processedPrices.reduce((latest: Date, price: any) =>
|
const latestDate = processedPrices.reduce((latest: Date, price: any) =>
|
||||||
price.date > latest ? price.date : latest,
|
price.dateTime > latest ? price.dateTime : latest,
|
||||||
new Date(0)
|
new Date(0)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -114,26 +127,26 @@ export async function updatePrices(
|
||||||
});
|
});
|
||||||
|
|
||||||
this.logger.info('Prices updated successfully', {
|
this.logger.info('Prices updated successfully', {
|
||||||
symbol,
|
qmSearchCode,
|
||||||
priceCount: priceData.length,
|
priceCount: priceData.length,
|
||||||
latestDate
|
latestDate
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
symbol,
|
qmSearchCode,
|
||||||
message: `Prices updated for ${symbol}`,
|
message: `Prices updated for ${qmSearchCode}`,
|
||||||
data: {
|
data: {
|
||||||
count: priceData.length,
|
count: priceData.length,
|
||||||
latestDate
|
latestDate
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
this.logger.warn('No price data returned from API', { symbol });
|
this.logger.warn('No price data returned from API', { qmSearchCode });
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
symbol,
|
qmSearchCode,
|
||||||
message: `No price data found for symbol ${symbol}`
|
message: `No price data found for qmSearchCode ${qmSearchCode}`
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -144,7 +157,7 @@ export async function updatePrices(
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logger.error('Error fetching prices', {
|
this.logger.error('Error fetching prices', {
|
||||||
symbol,
|
qmSearchCode,
|
||||||
error: error instanceof Error ? error.message : 'Unknown error'
|
error: error instanceof Error ? error.message : 'Unknown error'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -156,7 +169,7 @@ export async function updatePrices(
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
symbol,
|
qmSearchCode,
|
||||||
message: `Failed to fetch prices: ${error instanceof Error ? error.message : 'Unknown error'}`
|
message: `Failed to fetch prices: ${error instanceof Error ? error.message : 'Unknown error'}`
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -177,7 +190,7 @@ export async function schedulePriceUpdates(
|
||||||
symbolsQueued: number;
|
symbolsQueued: number;
|
||||||
errors: number;
|
errors: number;
|
||||||
}> {
|
}> {
|
||||||
const { limit = 100, forceUpdate = false } = input;
|
const { limit = 1, forceUpdate = false } = input;
|
||||||
const tracker = await getOperationTracker(this);
|
const tracker = await getOperationTracker(this);
|
||||||
|
|
||||||
this.logger.info('Scheduling price updates', { limit, forceUpdate });
|
this.logger.info('Scheduling price updates', { limit, forceUpdate });
|
||||||
|
|
@ -219,8 +232,6 @@ export async function schedulePriceUpdates(
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.scheduleOperation('update-prices', {
|
await this.scheduleOperation('update-prices', {
|
||||||
symbol: doc.symbol,
|
|
||||||
symbolId: doc.symbolId,
|
|
||||||
qmSearchCode: doc.qmSearchCode
|
qmSearchCode: doc.qmSearchCode
|
||||||
}, {
|
}, {
|
||||||
priority: 7, // High priority for price data
|
priority: 7, // High priority for price data
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,13 @@ import { getRandomUserAgent } from "@stock-bot/utils";
|
||||||
export const QM_SESSION_IDS = {
|
export const QM_SESSION_IDS = {
|
||||||
LOOKUP: 'dc8c9930437f65d30f6597768800957017bac203a0a50342932757c8dfa158d6', // lookup endpoint
|
LOOKUP: 'dc8c9930437f65d30f6597768800957017bac203a0a50342932757c8dfa158d6', // lookup endpoint
|
||||||
SYMBOL: '1e1d7cb1de1fd2fe52684abdea41a446919a5fe12776dfab88615ac1ce1ec2f6', // getProfiles
|
SYMBOL: '1e1d7cb1de1fd2fe52684abdea41a446919a5fe12776dfab88615ac1ce1ec2f6', // getProfiles
|
||||||
|
PRICES: '5ad521e05faf5778d567f6d0012ec34d6cdbaeb2462f41568f66558bc7b4ced9', // getEnhancedChartData
|
||||||
// EDS: '', //
|
// EDS: '', //
|
||||||
// FILINGS: '', //
|
// FILINGS: '', //
|
||||||
// PRICES: '', //
|
// PRICES: '', //
|
||||||
// FINANCIALS: '', //
|
// FINANCIALS: '', //
|
||||||
// INTRADAY: '', //
|
// INTRADAY: '', //
|
||||||
|
// '5ad521e05faf5778d567f6d0012ec34d6cdbaeb2462f41568f66558bc7b4ced9' // getEhnachedChartData
|
||||||
// '5ad521e05faf5778d567f6d0012ec34d6cdbaeb2462f41568f66558bc7b4ced9': [], //4488d072b
|
// '5ad521e05faf5778d567f6d0012ec34d6cdbaeb2462f41568f66558bc7b4ced9': [], //4488d072b
|
||||||
// cc1cbdaf040f76db8f4c94f7d156b9b9b716e1a7509ec9c74a48a47f6b6b9f87: [], //97ff00cf3 // getQuotes
|
// cc1cbdaf040f76db8f4c94f7d156b9b9b716e1a7509ec9c74a48a47f6b6b9f87: [], //97ff00cf3 // getQuotes
|
||||||
// '74963ff42f1db2320d051762b5d3950ff9eab23f9d5c5b592551b4ca0441d086': [], //32ca24e394b // getSplitsBySymbol getBrokerRatingsBySymbol getDividendsBySymbol getEarningsSurprisesBySymbol getEarningsEventsBySymbol
|
// '74963ff42f1db2320d051762b5d3950ff9eab23f9d5c5b592551b4ca0441d086': [], //32ca24e394b // getSplitsBySymbol getBrokerRatingsBySymbol getDividendsBySymbol getEarningsSurprisesBySymbol getEarningsEventsBySymbol
|
||||||
|
|
@ -35,6 +37,7 @@ export const QM_CONFIG = {
|
||||||
SESSION_PATH: '/auth/g/authenticate/dataTool/v0/500',
|
SESSION_PATH: '/auth/g/authenticate/dataTool/v0/500',
|
||||||
LOOKUP_URL: 'https://app.quotemedia.com/datatool/lookup.json',
|
LOOKUP_URL: 'https://app.quotemedia.com/datatool/lookup.json',
|
||||||
SYMBOL_URL: 'https://app.quotemedia.com/datatool/getProfiles.json',
|
SYMBOL_URL: 'https://app.quotemedia.com/datatool/getProfiles.json',
|
||||||
|
PRICES_URL: 'https://app.quotemedia.com/datatool/getEnhancedChartData.json',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
// Session management settings
|
// Session management settings
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue