Maison >interface Web >js tutoriel >Création d'un générateur de rapports boursiers de haute qualité avec les API Node.js, Express et OpenAI

Création d'un générateur de rapports boursiers de haute qualité avec les API Node.js, Express et OpenAI

Barbara Streisand
Barbara Streisandoriginal
2024-11-04 14:54:43668parcourir

Building a High-Quality Stock Report Generator with Node.js, Express, and OpenAI API

Dans cet article, nous aborderons la création d'un générateur de rapports boursiers de qualité professionnelle à l'aide de Node.js, Express et de l'API OpenAI. Notre objectif sera d'écrire du code maintenable de haute qualité tout en préservant l'intégrité des messages d'invite utilisés dans les interactions de l'API OpenAI. L'application récupérera des données boursières, effectuera une analyse du sentiment et du secteur et générera un rapport d'investissement complet.

Table des matières

  1. Aperçu du projet
  2. Configuration de l'environnement
  3. Création du serveur Express
  4. Récupération et traitement des données
  5. Intégration avec l'API OpenAI
  6. Génération du rapport final
  7. Test de l'application
  8. Conclusion

Aperçu du projet

Notre objectif est de créer un point de terminaison d'API qui génère un rapport d'investissement détaillé pour un symbole boursier donné. Le rapport comprendra :

  • Présentation de l'entreprise
  • Performance financière
  • Discussion et analyse de gestion (MDA)
  • Analyse des sentiments
  • Analyse de l'industrie
  • Risques et opportunités
  • Recommandation d'investissement

Nous récupérerons les données boursières à partir d'API externes et utiliserons l'API OpenAI pour une analyse avancée, garantissant ainsi que les messages d'invite sont conservés avec précision.

Configuration de l'environnement

Conditions préalables

  • Node.js installé sur votre machine
  • Clé API OpenAI (Si vous n'en avez pas, inscrivez-vous sur OpenAI)

Initialisation du projet

Créez un nouveau répertoire et initialisez un projet Node.js :

mkdir stock-report-generator
cd stock-report-generator
npm init -y

Installez les dépendances nécessaires :

npm install express axios

Mettre en place la structure du projet :

mkdir routes utils data
touch app.js routes/report.js utils/helpers.js

Création du serveur express

Configuration de app.js

// app.js
const express = require('express');
const reportRouter = require('./routes/report');

const app = express();

app.use(express.json());
app.use('/api', reportRouter);

const PORT = process.env.PORT || 3000;

app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});
  • Initialisation Express : Importez Express et initialisez l'application.
  • Middleware : utilisez express.json() pour analyser les corps de requête JSON.
  • Routage : Montez le routeur de rapports sur le chemin /api.
  • Écoute du serveur : démarrez le serveur sur le port spécifié.

Récupération et traitement des données

Création de fonctions d'assistance

Dans utils/helpers.js, nous définirons des fonctions utilitaires pour la récupération et le traitement des données.

mkdir stock-report-generator
cd stock-report-generator
npm init -y
  • getLastYearDates : calcule les dates de début et de fin de l'année précédente.
  • objectToString : convertit un objet en chaîne lisible, à l'exclusion des clés spécifiées.
  • fetchData : gère les requêtes GET vers des API externes, renvoyant des données ou une valeur par défaut.
  • readLocalJson : lit les données des fichiers JSON locaux.

Implémentation de la récupération des données boursières

Dans routes/report.js, définissez des fonctions pour récupérer les données boursières.

npm install express axios
  • fetchStockData : récupère simultanément plusieurs points de données et traite les résultats.
  • Traitement des données : Formate et transforme les données pour une utilisation ultérieure.
  • Gestion des erreurs : enregistre les erreurs et les renvoie pour une gestion de niveau supérieur.

Intégration avec l'API OpenAI

Fonction d'interaction avec l'API OpenAI

mkdir routes utils data
touch app.js routes/report.js utils/helpers.js
  • analyzeWithOpenAI : gère la communication avec l'API OpenAI.
  • Configuration API : définit des paramètres tels que le modèle et la température.
  • Gestion des erreurs : enregistre et renvoie les erreurs pour la gestion en amont.

Effectuer une analyse des sentiments

// app.js
const express = require('express');
const reportRouter = require('./routes/report');

const app = express();

app.use(express.json());
app.use('/api', reportRouter);

const PORT = process.env.PORT || 3000;

app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});
  • performSentimentAnalysis : construit des messages d'invite et appelle l'API OpenAI pour analyse.
  • Conception des invites : garantit que les messages d'invite sont clairs et incluent le contexte nécessaire.

Analyser l'industrie

// utils/helpers.js
const axios = require('axios');
const fs = require('fs');
const path = require('path');

const BASE_URL = 'https://your-data-api.com'; // Replace with your actual data API

/**
 * Get the start and end dates for the last year.
 * @returns {object} - An object containing `start` and `end` dates.
 */
function getLastYearDates() {
  const now = new Date();
  const end = now.toISOString().split('T')[0];
  now.setFullYear(now.getFullYear() - 1);
  const start = now.toISOString().split('T')[0];
  return { start, end };
}

/**
 * Convert an object to a string, excluding specified keys.
 * @param {object} obj - The object to convert.
 * @param {string[]} excludeKeys - Keys to exclude.
 * @returns {string} - The resulting string.
 */
function objectToString(obj, excludeKeys = []) {
  return Object.entries(obj)
    .filter(([key]) => !excludeKeys.includes(key))
    .map(([key, value]) => `${key}: ${value}`)
    .join('\n');
}

/**
 * Fetch data from a specified endpoint with given parameters.
 * @param {string} endpoint - API endpoint.
 * @param {object} params - Query parameters.
 * @param {any} defaultValue - Default value if the request fails.
 * @returns {Promise<any>} - The fetched data or default value.
 */
async function fetchData(endpoint, params = {}, defaultValue = null) {
  try {
    const response = await axios.get(`${BASE_URL}${endpoint}`, { params });
    return response.data || defaultValue;
  } catch (error) {
    console.error(`Error fetching data from ${endpoint}:`, error.message);
    return defaultValue;
  }
}

/**
 * Read data from a local JSON file.
 * @param {string} fileName - Name of the JSON file.
 * @returns {any} - The parsed data.
 */
function readLocalJson(fileName) {
  const filePath = path.join(__dirname, '../data', fileName);
  const data = fs.readFileSync(filePath, 'utf-8');
  return JSON.parse(data);
}

module.exports = {
  fetchData,
  objectToString,
  getLastYearDates,
  readLocalJson,
};
  • analyzeIndustry : similaire à l'analyse des sentiments, mais se concentre sur un contexte industriel plus large.
  • Conservation des invites : préserve l'intégrité des messages d'invite d'origine.

Génération du rapport final

Compilation de toutes les données

// routes/report.js
const express = require('express');
const {
  fetchData,
  objectToString,
  getLastYearDates,
  readLocalJson,
} = require('../utils/helpers');

const router = express.Router();

/**
 * Fetches stock data including historical prices, financials, MDA, and main business info.
 * @param {string} ticker - Stock ticker symbol.
 * @returns {Promise<object>} - An object containing all fetched data.
 */
async function fetchStockData(ticker) {
  try {
    const dates = getLastYearDates();
    const [historicalData, financialData, mdaData, businessData] = await Promise.all([
      fetchData('/stock_zh_a_hist', {
        symbol: ticker,
        period: 'weekly',
        start_date: dates.start,
        end_date: dates.end,
      }, []),

      fetchData('/stock_financial_benefit_ths', {
        code: ticker,
        indicator: '按年度',
      }, [{}]),

      fetchData('/stock_mda', { code: ticker }, []),

      fetchData('/stock_main_business', { code: ticker }, []),
    ]);

    const hist = historicalData[historicalData.length - 1];
    const currentPrice = (hist ? hist['开盘'] : 'N/A') + ' CNY';
    const historical = historicalData
      .map((item) => objectToString(item, ['股票代码']))
      .join('\n----------\n');

    const zsfzJson = readLocalJson('zcfz.json');
    const balanceSheet = objectToString(zsfzJson.find((item) => item['股票代码'] === ticker));

    const financial = objectToString(financialData[0]);

    const mda = mdaData.map(item => `${item['报告期']}\n${item['内容']}`).join('\n-----------\n');

    const mainBusiness = businessData.map(item =>
      `主营业务: ${item['主营业务']}\n产品名称: ${item['产品名称']}\n产品类型: ${item['产品类型']}\n经营范围: ${item['经营范围']}`
    ).join('\n-----------\n');

    return { currentPrice, historical, balanceSheet, mda, mainBusiness, financial };
  } catch (error) {
    console.error('Error fetching stock data:', error.message);
    throw error;
  }
}
  • provideFinalAnalysis : élabore soigneusement des messages rapides, intégrant toutes les données collectées.
  • Intégrité de l'invite : garantit que les messages d'invite d'origine ne sont pas altérés ou corrompus.

Tester l'application

Définir le gestionnaire de route

Ajoutez le gestionnaire de route dans routes/report.js :

const axios = require('axios');

const OPENAI_API_KEY = 'your-openai-api-key'; // Replace with your OpenAI API key

/**
 * Interacts with the OpenAI API to get completion results.
 * @param {array} messages - Array of messages, including system prompts and user messages.
 * @returns {Promise<string>} - The AI's response.
 */
async function analyzeWithOpenAI(messages) {
  try {
    const headers = {
      'Authorization': `Bearer ${OPENAI_API_KEY}`,
      'Content-Type': 'application/json',
    };
    const requestData = {
      model: 'gpt-4',
      temperature: 0.3,
      messages: messages,
    };

    const response = await axios.post(
      'https://api.openai.com/v1/chat/completions',
      requestData,
      { headers }
    );
    return response.data.choices[0].message.content.trim();
  } catch (error) {
    console.error('Error fetching analysis from OpenAI:', error.message);
    throw error;
  }
}
  • Validation d'entrée : Vérifie si le symbole boursier est fourni.
  • Collecte de données : récupère simultanément les données boursières et effectue des analyses.
  • Gestion des erreurs : enregistre les erreurs et envoie une réponse 500 en cas d'échec.

Démarrage du serveur

Assurez-vous que vos app.js et routes/report.js sont correctement configurés, puis démarrez le serveur :

/**
 * Performs sentiment analysis on news articles using the OpenAI API.
 * @param {string} ticker - Stock ticker symbol.
 * @returns {Promise<string>} - Sentiment analysis summary.
 */
async function performSentimentAnalysis(ticker) {
  const systemPrompt = `You are a sentiment analysis assistant. Analyze the sentiment of the given news articles for ${ticker} and provide a summary of the overall sentiment and any notable changes over time. Be measured and discerning. You are a skeptical investor.`;

  const tickerNewsResponse = await fetchData('/stock_news_specific', { code: ticker }, []);

  const newsText = tickerNewsResponse
    .map(item => `${item['文章来源']} Date: ${item['发布时间']}\n${item['新闻内容']}`)
    .join('\n----------\n');

  const messages = [
    { role: 'system', content: systemPrompt },
    {
      role: 'user',
      content: `News articles for ${ticker}:\n${newsText || 'N/A'}\n----\nProvide a summary of the overall sentiment and any notable changes over time.`,
    },
  ];

  return await analyzeWithOpenAI(messages);
}

Envoi d'une demande de test

Utilisez curl ou Postman pour envoyer une requête POST :

mkdir stock-report-generator
cd stock-report-generator
npm init -y
  • Réponse : Le serveur doit renvoyer un objet JSON contenant le rapport généré.

Conclusion

Nous avons construit un générateur de rapports de stock de haute qualité avec les capacités suivantes :

  • Récupération et traitement des données boursières à partir d'API externes.
  • Effectuer des analyses avancées à l'aide de l'API OpenAI.
  • Générer un rapport d'investissement complet, tout en garantissant l'intégrité des messages rapides.

Tout au long du processus de développement, nous nous sommes concentrés sur l'écriture d'un code professionnel et maintenable et avons fourni des explications et des annotations détaillées.

Meilleures pratiques mises en œuvre

  • Structure du code modulaire : les fonctions sont modularisées pour plus de réutilisabilité et de clarté.
  • Opérations asynchrones : utilisation de async/await et Promise.all pour une programmation asynchrone efficace.
  • Gestion des erreurs : blocs try-catch complets et messages d'erreur.
  • Abstraction API : logique d'interaction API séparée pour une meilleure maintenabilité.
  • Ingénierie des invites : messages d'invite soigneusement conçus pour que l'API OpenAI obtienne le résultat souhaité.
  • Validation d'entrée : vérification des paramètres d'entrée requis pour éviter les erreurs inutiles.
  • Documentation du code : ajout de commentaires JSDoc pour une meilleure compréhension et maintenance.

Prochaines étapes

  • Mise en cache : implémentez des mécanismes de mise en cache pour réduire les appels d'API redondants.
  • Authentification : sécurisez les points de terminaison de l'API avec l'authentification et la limitation du débit.
  • Développement Frontend : créez une interface utilisateur pour interagir avec l'application.
  • Analyses supplémentaires : incorporez une analyse technique ou d'autres modèles financiers.

Références

  • Documentation Node.js
  • Documentation Express.js
  • Documentation Axios
  • Référence de l'API OpenAI

Avertissement : Cette application est uniquement à des fins éducatives. Garantissez le respect de toutes les conditions de service de l'API et gérez les données sensibles de manière appropriée.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn