Skip to content

BloodyRose0714/stock-market-analyzer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rakeshsharmaspyne: add nest js cron

GitHub Copilot: Enable Claude Sonnet 3.5 for all clients [object Object]

rakeshsharmaspyne: @GitHubCopilot Enable: "Enable Claude Sonnet 3.5 for all clients"

GitHub Copilot: I'll help you add NestJS cron functionality to your application. You'll need to install the required package first and then modify the service to include a cron job.

  1. First, install the required package by running this in your terminal:
npm install @nestjs/schedule
  1. Then update your app.module.ts and app.service.ts files:
import { Module } from '@nestjs/common';
import { ScheduleModule } from '@nestjs/schedule';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [ScheduleModule.forRoot()],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}
import { Injectable } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';

@Injectable()
export class AppService {
  getHello(): string {
    return 'Hello World!';
  }

  @Cron(CronExpression.EVERY_10_SECONDS)
  handleCron() {
    console.log('Called every 10 seconds');
  }

  // Example of custom cron expression
  @Cron('45 * * * * *')
  handleCustomCron() {
    console.log('Called every minute at 45 seconds');
  }
}

This implementation:

  • Adds the ScheduleModule to your application
  • Creates two example cron jobs in the AppService
  • One runs every 10 seconds using predefined CronExpression
  • Another runs at 45 seconds of every minute using a custom cron expression

You can modify the cron expressions based on your needs. Some common CronExpression options:

  • EVERY_MINUTE
  • EVERY_HOUR
  • EVERY_DAY_AT_MIDNIGHT
  • EVERY_WEEK

For custom cron expressions, the format is: * * * * * * (seconds minutes hours day-of-month months day-of-week)

rakeshsharmaspyne: docker build -t market-anlayzer:1 . [+] Building 0.1s (1/1) FINISHED docker:desktop-linux => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 2B 0.0s ERROR: failed to solve: failed to read dockerfile: open Dockerfile: no such file or directory (base) smaclapotop-28@Rakesh-CM43 market-anlayzer %

GitHub Copilot: The error occurs because the Dockerfile has an incorrect name. It's named .Dockerfile but Docker looks for Dockerfile by default. Here's how to fix it:

  1. First, rename the file:
mv .Dockerfile Dockerfile
  1. Then, uncomment the build stage in the Dockerfile. Here's the corrected version:
# Build stage
FROM node:18-alpine AS builder

WORKDIR /app

COPY package*.json ./
RUN npm install

COPY . .
RUN npm run build

# Production stage
FROM node:18-alpine

WORKDIR /usr/src/app

COPY package.json ./
RUN npm install --only=production

COPY --from=builder /app/dist ./dist

EXPOSE 1337
CMD ["npm", "run", "start:prod"]
  1. Now you can build the Docker image:
docker build -t market-anlayzer:1 .

The error occurred because:

  1. The Dockerfile was hidden (started with a dot)
  2. The build stage was commented out, which would cause the --from=builder instruction to fail
  3. Docker by default looks for a file named exactly Dockerfile

After making these changes, the Docker build should work correctly.

rakeshsharmaspyne: [+] Building 2.1s (4/4) FINISHED docker:desktop-linux => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 417B 0.0s => ERROR [internal] load metadata for docker.io/library/builder:latest 2.0s => [internal] load metadata for docker.io/library/node:18-alpine 0.6s => [auth] library/builder:pull token for registry-1.docker.io 0.0s

[internal] load metadata for docker.io/library/builder:latest:


Dockerfile:20

18 | RUN npm install --only=production 19 | 20 | >>> COPY --from=builder /app/dist ./dist 21 | 22 | EXPOSE 1337

ERROR: failed to solve: builder: failed to resolve source metadata for docker.io/library/builder:latest: pull access denied, repository does not exist or may require authorization: server message: insufficient_scope: authorization failed

GitHub Copilot: The error occurs because the build stage is commented out but we're trying to copy from it. Let's fix the Dockerfile by uncommenting the build stage and ensuring proper syntax:

# Build stage
FROM node:18-alpine AS builder

WORKDIR /app

COPY package*.json ./
RUN npm install

COPY . .
RUN npm run build

# Production stage
FROM node:18-alpine

WORKDIR /usr/src/app

COPY package.json ./
RUN npm install --only=production

COPY --from=builder /app/dist ./dist

EXPOSE 1337
CMD ["npm", "run", "start:prod"]

Now you can build the Docker image again:

docker build -t market-anlayzer:1 .

The error occurred because:

  1. The build stage was commented out
  2. The COPY --from=builder instruction was trying to copy from a non-existent build stage
  3. Docker was attempting to pull a non-existent image called "builder"

This fix:

  1. Uncomments the build stage
  2. Creates a proper multi-stage build
  3. Properly sets up the builder stage with the AS builder alias
  4. Maintains the production stage that copies the built artifacts from the builder stage

rakeshsharmaspyne: in docker file i am using expose 1337 but in main file using 3000 docker run -d --rm -p 1337:1337 --name market-anlayzer 5b1872e1d20a 0f4e2e18a60436fbe6b8b7cbdefe90e108d8f6822baf428eecc94224aeb8b143

GitHub Copilot: I understand the port mismatch issue. If your NestJS application is running on port 3000 but Docker is exposing port 1337, you'll need to align these. Here's how to fix it:

  1. First, update your Dockerfile to use port 3000:
# Build stage
FROM node:18-alpine AS builder

WORKDIR /app

COPY package*.json ./
RUN npm install

COPY . .
RUN npm run build

# Production stage
FROM node:18-alpine

WORKDIR /usr/src/app

COPY package.json ./
RUN npm install --only=production

COPY --from=builder /app/dist ./dist

EXPOSE 3000
CMD ["npm", "run", "start:prod"]
  1. Then, update your Docker run command to map port 3000:
docker run -d --rm -p 3000:3000 --name market-anlayzer market-anlayzer:1

Alternatively, if you want to keep the external port as 1337 but your application runs on 3000 internally, use this command:

docker run -d --rm -p 1337:3000 --name market-anlayzer market-anlayzer:1

This maps:

  • External port 1337 (accessible from host) to
  • Internal port 3000 (where your NestJS app runs)

Make sure your NestJS main.ts file is using port 3000:

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
}

rakeshsharmaspyne: i want to use aws client where should i create it

GitHub Copilot: I'll help you set up the AWS client in your NestJS application. Here's a step-by-step guide:

  1. First, install the AWS SDK:
npm install @aws-sdk/client-s3
  1. Create a new service for AWS configurations:
import { Injectable } from '@nestjs/common';
import { S3Client } from '@aws-sdk/client-s3';

@Injectable()
export class AwsService {
    private readonly s3Client: S3Client;

    constructor() {
        this.s3Client = new S3Client({
            region: process.env.AWS_REGION || 'us-east-1',
            credentials: {
                accessKeyId: process.env.AWS_ACCESS_KEY_ID,
                secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
            },
        });
    }

    getS3Client(): S3Client {
        return this.s3Client;
    }
}
  1. Create AWS module:
import { Module } from '@nestjs/common';
import { AwsService } from './aws.service';

@Module({
    providers: [AwsService],
    exports: [AwsService],
})
export class AwsModule {}
  1. Update your AppModule to import the AWS module:
import { Module } from '@nestjs/common';
import { ScheduleModule } from '@nestjs/schedule';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { AwsModule } from './aws/aws.module';

@Module({
    imports: [
        ScheduleModule.forRoot(),
        AwsModule
    ],
    controllers: [AppController],
    providers: [AppService],
})
export class AppModule {}
  1. Now you can use the AWS client in your AppService:
import { Injectable } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { AwsService } from './aws/aws.service';

@Injectable()
export class AppService {
    constructor(private readonly awsService: AwsService) {}

    getHello(): string {
        return 'Hello World!';
    }

    @Cron(CronExpression.EVERY_10_SECONDS)
    async handleCron() {
        const s3Client = this.awsService.getS3Client();
        // Use s3Client here
        console.log('AWS S3 client ready');
    }
}
  1. Create a .env file in your project root:
AWS_ACCESS_KEY_ID=your_access_key
AWS_SECRET_ACCESS_KEY=your_secret_key
AWS_REGION=your_region

Don't forget to:

  • Add .env to your .gitignore file
  • Install @nestjs/config package for environment variables support:
npm install @nestjs/config

This structure:

  • Keeps AWS configuration isolated and reusable
  • Uses dependency injection
  • Follows NestJS best practices
  • Keeps credentials secure using environment variables

rakeshsharmaspyne: in handleCron i want to run mysql query , where should i create mysql connection

GitHub Copilot: Let me help you set up MySQL connection in your NestJS application.

  1. First, install the required dependencies:
npm install @nestjs/typeorm typeorm mysql2
  1. Create a database module and service:
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { DatabaseService } from './database.service';

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: process.env.DB_HOST || 'localhost',
      port: parseInt(process.env.DB_PORT) || 3306,
      username: process.env.DB_USERNAME || 'root',
      password: process.env.DB_PASSWORD || '',
      database: process.env.DB_NAME || 'market_analyzer',
      entities: [],
      synchronize: true,
    }),
  ],
  providers: [DatabaseService],
  exports: [DatabaseService],
})
export class DatabaseModule {}
op-28/githubspyne/market-anlayzer/src/database/database.service.ts
import { Injectable } from '@nestjs/common';
import { DataSource } from 'typeorm';

@Injectable()
export class DatabaseService {
  constructor(private dataSource: DataSource) {}

  async executeQuery(query: string, parameters?: any[]): Promise<any> {
    return await this.dataSource.query(query, parameters);
  }
}
  1. Update your AppModule to import the DatabaseModule:
import { Module } from '@nestjs/common';
import { ScheduleModule } from '@nestjs/schedule';
import { DatabaseModule } from './database/database.module';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [
    ScheduleModule.forRoot(),
    DatabaseModule,
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}
  1. Now you can use the database service in your AppService:
import { Injectable } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { AwsService } from './aws/aws.service';
import { DatabaseService } from './database/database.service';

@Injectable()
export class AppService {
  constructor(
    private readonly awsService: AwsService,
    private readonly databaseService: DatabaseService
  ) {}

  getHello(): string {
    return 'Hello World!';
  }

  @Cron(CronExpression.EVERY_10_SECONDS)
  async handleCron() {
    try {
      const result = await this.databaseService.executeQuery(
        'SELECT * FROM your_table WHERE condition = ?',
        ['value']
      );
      console.log('Query result:', result);
    } catch (error) {
      console.error('Database query failed:', error);
    }
  }
}
  1. Create a .env file in your project root:
DB_HOST=localhost
DB_PORT=3306
DB_USERNAME=your_username
DB_PASSWORD=your_password
DB_NAME=market_analyzer

Don't forget to:

  • Add .env to your .gitignore file
  • Install @nestjs/config if not already installed:
npm install @nestjs/config

This structure:

  • Uses TypeORM for database interactions
  • Follows NestJS dependency injection patterns
  • Keeps database logic isolated in a separate module
  • Uses environment variables for configuration
  • Provides error handling for database queries

Similar code found with 1 license type

rakeshsharmaspyne: let prompt = { "model": "gpt-4o", "temperature": 0.2, "input": [ { "role": "system", "content": `You are a professional equity research analyst specializing in public company analysis, stock performance tracking, and financial reporting interpretation.

For the given stock/company, prepare a complete analytical summary including:

  1. Market Prediction — analyst consensus (buy/sell/hold), sentiment trend, and target price range.
  2. Price Metrics — current market price, 52-week high/low, monthly average, and short-term movement (percentage change).
  3. Latest Company News — fetch only from verified company or exchange portals (NSE/BSE filings, company investor site) and top-tier financial media (Bloomberg, Moneycontrol, Economic Times, Reuters). Summarize headlines briefly.
  4. Quarterly Results — include revenue, profit, EPS, YoY and QoQ comparisons with numeric values.
  5. Major Developments — highlight recent partnerships, management commentary, product launches, or business shifts (last 30 days).
  6. Statistical Summary — show min, max, average, and percentage growth metrics for key figures (price, revenue, EPS).
  7. Outlook — provide both short-term and long-term outlook with reasoning (bullish, bearish, or neutral).

Return the data strictly as JSON with the following structure: { "Stock Name": string, "Predictions": { "Analyst Consensus": string, "Target Price": number, "Sentiment": string }, "Price Metrics": { "Current Price": number, "52WeekHigh": number, "52WeekLow": number, "MonthlyAverage": number, "DailyChangePercent": number }, "Latest News": [ { "Headline": string, "Summary": string, "Source": string, "Date": string } ], "Quarterly Results": { "Revenue": { "Current": number, "YoYChangePercent": number, "QoQChangePercent": number }, "NetProfit": { "Current": number, "YoYChangePercent": number, "QoQChangePercent": number }, "EPS": { "Current": number, "YoYChangePercent": number, "QoQChangePercent": number } }, "Recent Developments": [ { "Title": string, "Description": string, "Date": string } ], "Statistical Summary": { "MinValue": number, "MaxValue": number, "AverageValue": number, "GrowthPercent": number }, "Outlook": { "ShortTerm": string, "LongTerm": string, "Reasoning": string } }}, { "role": "user", "content":Stock: ${stock_name}\nFetch all the above information from reliable and verified sources (NSE/BSE filings, company portal, or top financial websites). Return the final result strictly in JSON format.` } ] }

i want to add this file where should i add this

GitHub Copilot: I'll help you create a new service for stock analysis. Here's how to structure it:

  1. First, create a new stock analysis service:
import { Injectable } from '@nestjs/common';

interface StockAnalysis {
  StockName: string;
  Predictions: {
    AnalystConsensus: string;
    TargetPrice: number;
    Sentiment: string;
  };
  PriceMetrics: {
    CurrentPrice: number;
    '52WeekHigh': number;
    '52WeekLow': number;
    MonthlyAverage: number;
    DailyChangePercent: number;
  };
  LatestNews: Array<{
    Headline: string;
    Summary: string;
    Source: string;
    Date: string;
  }>;
  QuarterlyResults: {
    Revenue: {
      Current: number;
      YoYChangePercent: number;
      QoQChangePercent: number;
    };
    NetProfit: {
      Current: number;
      YoYChangePercent: number;
      QoQChangePercent: number;
    };
    EPS: {
      Current: number;
      YoYChangePercent: number;
      QoQChangePercent: number;
    };
  };
  RecentDevelopments: Array<{
    Title: string;
    Description: string;
    Date: string;
  }>;
  StatisticalSummary: {
    MinValue: number;
    MaxValue: number;
    AverageValue: number;
    GrowthPercent: number;
  };
  Outlook: {
    ShortTerm: string;
    LongTerm: string;
    Reasoning: string;
  };
}

@Injectable()
export class StockAnalysisService {
  async analyzeStock(stockName: string): Promise<StockAnalysis> {
    // Implement your stock analysis logic here
    // This is where you'll fetch data from various sources
    return {
      StockName: stockName,
      Predictions: {
        AnalystConsensus: 'Buy',
        TargetPrice: 0,
        Sentiment: 'Positive'
      },
      // ... implement other fields
    };
  }
}
  1. Create a stock module:
import { Module } from '@nestjs/common';
import { StockAnalysisService } from './stock-analysis.service';

@Module({
  providers: [StockAnalysisService],
  exports: [StockAnalysisService]
})
export class StockModule {}
  1. Update your AppService to use the stock analysis:
import { Injectable } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { AwsService } from './aws/aws.service';
import { DatabaseService } from './database/database.service';
import { StockAnalysisService } from './stock/stock-analysis.service';

@Injectable()
export class AppService {
    constructor(
      private readonly awsService: AwsService,
      private readonly databaseService: DatabaseService,
      private readonly stockAnalysisService: StockAnalysisService
    ) {}

    @Cron(CronExpression.EVERY_10_SECONDS)
    async handleCron() {
      try {
        const stocks = await this.databaseService.executeQuery(
          'SELECT * FROM stock_cron_config WHERE is_active = 1 AND next_run_at <= NOW()',
          []
        );

        for (const stock of stocks) {
          const analysis = await this.stockAnalysisService.analyzeStock(stock.name);
          console.log('Stock analysis:', analysis);
          // Store analysis results or send to AWS
        }
      } catch (error) {
        console.error('Stock analysis failed:', error);
      }
    }
}
  1. Update your AppModule to include the new StockModule:
import { Module } from '@nestjs/common';
import { ScheduleModule } from '@nestjs/schedule';
import { DatabaseModule } from './database/database.module';
import { AwsModule } from './aws/aws.module';
import { StockModule } from './stock/stock.module';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [
    ScheduleModule.forRoot(),
    DatabaseModule,
    AwsModule,
    StockModule
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

This structure:

  • Separates stock analysis logic into its own service
  • Uses TypeScript interfaces for type safety
  • Integrates with your existing cron job
  • Follows NestJS module organization patterns
  • Keeps the code maintainable and testable

Don't forget to implement the actual stock analysis logic in the analyzeStock method of StockAnalysisService according to your data sources and requirements.

rakeshsharmaspyne: this is only prompt which i will gite it to the chatgpt

GitHub Copilot: I'll help you structure this prompt configuration for your NestJS application.

  1. First, create a config folder and prompt configuration file:
export const STOCK_ANALYSIS_PROMPT = {
  model: "gpt-4",
  temperature: 0.2,
  input: [
    {
      role: "system",
      content: `You are a professional equity research analyst specializing in public company analysis, stock performance tracking, and financial reporting interpretation...`
    },
    {
      role: "user",
      content: `Stock: \${stockName}\nFetch all the above information from reliable and verified sources...`
    }
  ]
};
  1. Create a prompt service to handle the template:
import { Injectable } from '@nestjs/common';
import { STOCK_ANALYSIS_PROMPT } from '../config/prompt.config';

@Injectable()
export class PromptService {
  generateStockAnalysisPrompt(stockName: string): any {
    return {
      ...STOCK_ANALYSIS_PROMPT,
      input: STOCK_ANALYSIS_PROMPT.input.map(input => ({
        ...input,
        content: input.content.replace('${stockName}', stockName)
      }))
    };
  }
}
  1. Update your app service to use the prompt:
import { Injectable } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { AwsService } from './aws/aws.service';
import { DatabaseService } from './database/database.service';
import { PromptService } from './prompt/prompt.service';

@Injectable()
export class AppService {
    constructor(
        private readonly awsService: AwsService,
        private readonly databaseService: DatabaseService,
        private readonly promptService: PromptService
    ) {}

    @Cron(CronExpression.EVERY_10_SECONDS)
    async handleCron() {
        try {
            const stocks = await this.databaseService.executeQuery(
                'SELECT * FROM stock_cron_config WHERE is_active = 1 AND next_run_at <= NOW()',
                []
            );

            for (const stock of stocks) {
                const prompt = this.promptService.generateStockAnalysisPrompt(stock.name);
                // Use prompt with your AI service
                console.log('Generated prompt:', prompt);
            }
        } catch (error) {
            console.error('Failed to process stocks:', error);
        }
    }
}
  1. Create a prompt module:
import { Module } from '@nestjs/common';
import { PromptService } from './prompt.service';

@Module({
    providers: [PromptService],
    exports: [PromptService]
})
export class PromptModule {}
  1. Update your app module:
import { Module } from '@nestjs/common';
import { ScheduleModule } from '@nestjs/schedule';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { PromptModule } from './prompt/prompt.module';

@Module({
    imports: [
        ScheduleModule.forRoot(),
        PromptModule
    ],
    controllers: [AppController],
    providers: [AppService],
})
export class AppModule {}

This structure:

  • Separates prompt configuration into its own module
  • Makes prompts reusable and maintainable
  • Follows NestJS best practices
  • Provides type safety with TypeScript
  • Allows for easy modification of prompt templates

Remember to install any required dependencies and handle the actual AI service integration separately.

rakeshsharmaspyne: let result = await axios.post('https://api.openai.com/v1/responses', prompt, { headers: { 'Authorization': Bearer ${sails.config.custom.openaiKey} } })

        where should i add this

GitHub Copilot: Let's add the OpenAI API call to your PromptService. First, install the required package:

npm install axios

Then modify your PromptService:

import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import axios from 'axios';
import { STOCK_ANALYSIS_PROMPT } from '../config/prompt.config';

@Injectable()
export class PromptService {
  constructor(private configService: ConfigService) {}

  generateStockAnalysisPrompt(stockName: string): any {
    return {
      ...STOCK_ANALYSIS_PROMPT,
      input: STOCK_ANALYSIS_PROMPT.input.map(input => ({
        ...input,
        content: input.content.replace('${stockName}', stockName)
      }))
    };
  }

  async getOpenAIResponse(prompt: any): Promise<any> {
    try {
      const result = await axios.post('https://api.openai.com/v1/responses', prompt, {
        headers: {
          'Authorization': `Bearer ${this.configService.get('OPENAI_API_KEY')}`,
          'Content-Type': 'application/json'
        }
      });
      return result.data;
    } catch (error) {
      console.error('OpenAI API call failed:', error.response?.data || error.message);
      throw error;
    }
  }

  async analyzeStock(stockName: string): Promise<any> {
    const prompt = this.generateStockAnalysisPrompt(stockName);
    return await this.getOpenAIResponse(prompt);
  }
}

Add environment variable to your .env file:

OPENAI_API_KEY=your_openai_api_key_here

Make sure to install @nestjs/config if not already installed:

npm install @nestjs/config

Update your AppModule to use ConfigModule:

import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { ScheduleModule } from '@nestjs/schedule';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { PromptModule } from './prompt/prompt.module';

@Module({
  imports: [
    ConfigModule.forRoot(),
    ScheduleModule.forRoot(),
    PromptModule
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

Now you can use the updated service in your AppService:

@Cron(CronExpression.EVERY_30_SECONDS)
async handleCron() {
  try {
    const stocks = await this.databaseService.executeQuery(
      'SELECT * FROM stock_cron_config WHERE is_active = 1 AND next_run_at <= NOW()',
      []
    );

    for (const stock of stocks) {
      const analysis = await this.promptService.analyzeStock(stock.name);
      console.log('Stock analysis:', analysis);
    }
  } catch (error) {
    console.error('Analysis failed:', error);
  }
}

This implementation:

  • Adds proper error handling
  • Uses environment variables for API key
  • Separates API call logic
  • Provides a clean interface for stock analysis
  • Follows NestJS best practices

rakeshsharmaspyne: now i want to use mongodb

GitHub Copilot: I'll help you modify the DatabaseService to use MongoDB instead of TypeORM. First, install the required packages:

npm install @nestjs/mongoose mongoose

Then update your DatabaseService:

import { Injectable } from '@nestjs/common';
import { InjectConnection } from '@nestjs/mongoose';
import { Connection } from 'mongoose';

@Injectable()
export class DatabaseService {
  constructor(@InjectConnection() private connection: Connection) {}

  async executeQuery(collection: string, query: any): Promise<any> {
    try {
      const result = await this.connection
        .collection(collection)
        .find(query)
        .toArray();
      return result;
    } catch (error) {
      console.error('MongoDB query failed:', error);
      throw error;
    }
  }

  async insertDocument(collection: string, document: any): Promise<any> {
    try {
      return await this.connection
        .collection(collection)
        .insertOne(document);
    } catch (error) {
      console.error('MongoDB insert failed:', error);
      throw error;
    }
  }
}

Create a new Database Module:

import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { DatabaseService } from './database.service';

@Module({
  imports: [
    MongooseModule.forRoot('mongodb://localhost:27017/market_analyzer', {
      useNewUrlParser: true,
      useUnifiedTopology: true,
    }),
  ],
  providers: [DatabaseService],
  exports: [DatabaseService],
})
export class DatabaseModule {}

Update your AppService to use MongoDB queries:

@Cron(CronExpression.EVERY_30_SECONDS)
async handleCron() {
  try {
    const result = await this.databaseService.executeQuery('stock_cron_config', {
      is_active: 1,
      next_run_at: { $lte: new Date() }
    });
    // ...rest of your code...
  } catch (error) {
    console.error('Database query failed:', error);
  }
}

Add MongoDB connection details to your .env file:

MONGODB_URI=mongodb://localhost:27017/market_analyzer

This implementation:

  • Uses Mongoose for MongoDB integration
  • Provides basic query and insert operations
  • Includes error handling
  • Uses environment variables for configuration
  • Follows NestJS best practices for MongoDB integration

Make sure MongoDB is installed and running on your Mac. You can install it using Homebrew:

brew install mongodb-community
brew services start mongodb-community

rakeshsharmaspyne: Object literal may only specify known properties, and 'useNewUrlParser' does not exist in type 'MongooseModuleOptions'.ts(2353)

GitHub Copilot: The error occurs because recent versions of Mongoose have deprecated some options. Let's update the MongoDB connection options in your database module:

import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { DatabaseService } from './database.service';

@Module({
  imports: [
    MongooseModule.forRoot('mongodb://localhost:27017/market_analyzer'),
  ],
  providers: [DatabaseService],
  exports: [DatabaseService],
})
export class DatabaseModule {}

For better configuration management, you can also use environment variables:

import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { DatabaseService } from './database.service';

@Module({
  imports: [
    MongooseModule.forRootAsync({
      imports: [ConfigModule],
      useFactory: async (configService: ConfigService) => ({
        uri: configService.get<string>('MONGODB_URI'),
      }),
      inject: [ConfigService],
    }),
  ],
  providers: [DatabaseService],
  exports: [DatabaseService],
})
export class DatabaseModule {}

Then add to your .env file:

MONGODB_URI=mongodb://localhost:27017/market_analyzer

The changes:

  • Removed deprecated options
  • Added ConfigModule support for environment variables
  • Uses async configuration
  • Follows current Mongoose best practices

Make sure you have installed the required packages:

npm install @nestjs/config @nestjs/mongoose mongoose

Similar code found with 1 license type

rakeshsharmaspyne: i have create stock schema with stock service i want to use in app.service.ts

GitHub Copilot: I'll help you integrate the StockService into your AppService. Here's how to do it:

  1. First, make sure your StockModule exports the StockService:
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { StockService } from './stock.service';
import { Stock, StockSchema } from './schemas/stock.schema';

@Module({
  imports: [
    MongooseModule.forFeature([{ name: Stock.name, schema: StockSchema }])
  ],
  providers: [StockService],
  exports: [StockService]
})
export class StockModule {}
  1. Update your AppService to use the StockService:
import { Injectable } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { MySQLDatabaseService } from './database/mysql/mysql.service';
import { MongoDatabaseService } from './database/mongo/mongo.service';
import { PromptService } from './prompt/prompt.service';
import { StockService } from './stock/stock.service';

@Injectable()
export class AppService {
    constructor(
        private readonly mysqlDB: MySQLDatabaseService,
        private readonly mongoDB: MongoDatabaseService,
        private readonly promptService: PromptService,
        private readonly stockService: StockService
    ) {}

    @Cron(CronExpression.EVERY_30_SECONDS)
    async handleCron() {
        try {
            const result = await this.mysqlDB.executeQuery(
                'SELECT * FROM stock_cron_config WHERE is_active = 1 AND next_run_at <= NOW()',
                []
            );

            const analysis = await this.promptService.analyzeStock(result[0].name);
            let responseText = analysis?.output?.[0]?.content?.[0]?.text;
            let cleanJson = responseText.replace(/```json\n|```/g, '');
            let jsonData = JSON.parse(cleanJson);

            // Save the analysis to MongoDB
            await this.stockService.createStock({
                name: result[0].name,
                analysis: jsonData,
                createdAt: new Date()
            });

            console.log('Query result:', result);
            console.log('Generated Prompt:', jsonData);
        } catch (error) {
            console.error('Analysis failed:', error);
        }
    }
}
  1. Update your AppModule to import the StockModule:
import { Module } from '@nestjs/common';
import { ScheduleModule } from '@nestjs/schedule';
import { StockModule } from './stock/stock.module';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
    imports: [
        ScheduleModule.forRoot(),
        StockModule,
        // ...other modules
    ],
    controllers: [AppController],
    providers: [AppService],
})
export class AppModule {}

This setup:

  • Injects the StockService into AppService
  • Uses the createStock method to save analysis results
  • Properly structures the modules and dependencies
  • Maintains separation of concerns
  • Follows NestJS dependency injection patterns

Now your cron job will:

  1. Fetch stocks from MySQL
  2. Get analysis from the prompt service
  3. Save the results to MongoDB using the StockService

rakeshsharmaspyne: also add below information while createing entry in mongodb export class Stock { @Prop({ required: true, unique: true }) stockId: string;

@Prop({ required: true }) stockName: string;

@Prop({ required: true, enum: ['mid', 'large', 'small'], default: 'mid' }) stockSize: 'mid' | 'large' | 'small';

@Prop() stockDescription?: string;

// ✅ Added fields @Prop({ required: true, unique: true, uppercase: true }) symbol: string; // e.g., "TCS", "INFY", "WIPRO"

@Prop({ required: true, enum: ['NSE', 'BSE'], default: 'NSE' }) exchange: 'NSE' | 'BSE';

@Prop({ type: Number, required: true }) currentPrice: number; // current market price

@Prop({ type: Number, default: 0 }) changePercent?: number; // percentage change

@Prop({ type: Number, default: 0 }) volume?: number; // traded volume

@Prop({ type: String }) sector?: string; // IT, Banking, Pharma, etc.

@Prop({ type: Boolean, default: true }) isActive: boolean;

@Prop({ type: Date }) lastUpdatedAt?: Date; }

GitHub Copilot: I'll help you update the AppService to include all the required stock information when creating an entry in MongoDB. Here's the modified code:

import { Injectable } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { MySQLDatabaseService } from './database/mysql/mysql.service';
import { MongoDatabaseService } from './database/mongo/mongo.service';
import { PromptService } from './prompt/prompt.service';
import { StockService } from './stock/stock.service';

@Injectable()
export class AppService {
    constructor(
        private readonly mysqlDB: MySQLDatabaseService,
        private readonly mongoDB: MongoDatabaseService,
        private readonly promptService: PromptService,
        private readonly stockService: StockService
    ) {}

    @Cron(CronExpression.EVERY_30_SECONDS)
    async handleCron() {
        try {
            const result = await this.mysqlDB.executeQuery(
                'SELECT * FROM stock_cron_config WHERE is_active = 1 AND next_run_at <= NOW()',
                []
            );

            const analysis = await this.promptService.analyzeStock(result[0].name);
            let responseText = analysis?.output?.[0]?.content?.[0]?.text;
            let cleanJson = responseText.replace(/```json\n|```/g, '');
            let jsonData = JSON.parse(cleanJson);

            // Create stock entry with all required fields
            await this.stockService.createStock({
                stockName: result[0].name,
                stockSize: 'mid', // You might want to determine this based on market cap
                stockDescription: jsonData.Outlook.Reasoning,
                symbol: result[0].symbol.toUpperCase(),
                exchange: 'NSE', // Or get from your configuration
                currentPrice: jsonData.PriceMetrics.CurrentPrice,
                changePercent: jsonData.PriceMetrics.DailyChangePercent,
                volume: jsonData.PriceMetrics.Volume || 0,
                sector: result[0].sector || 'Unknown',
                isActive: true,
                lastUpdatedAt: new Date(),
                analysis: jsonData // Additional analysis data
            });

            console.log('Stock analysis saved successfully');
        } catch (error) {
            console.error('Analysis failed:', error);
        }
    }
}

You'll also need to update your MySQL query to include the additional fields:

SELECT
    name,
    symbol,
    sector,
    is_active,
    next_run_at
FROM stock_cron_config
WHERE is_active = 1
AND next_run_at <= NOW()

This implementation:

  • Includes all fields from your Stock schema
  • Sets default values where appropriate
  • Handles the timestamp automatically
  • Maps the AI analysis data to the correct fields
  • Maintains data integrity with required fields
  • Uses uppercase for stock symbols
  • Includes error handling

Make sure your MySQL database table stock_cron_config has the corresponding columns to provide this information.

rakeshsharmaspyne: ERROR [ExceptionHandler] UnknownDependenciesException [Error]: Nest can't resolve dependencies of the AppService (MySQLDatabaseService, MongoDatabaseService, PromptService, ?). Please make sure that the argument StockService at index [3] is available in the AppModule context.

Potential solutions:

  • Is AppModule a valid NestJS module?
  • If StockService is a provider, is it part of the current AppModule?
  • If StockService is exported from a separate @Module, is that module imported within AppModule? @Module({ imports: [ /* the Module containing StockService */ ] })

For more common dependency resolution issues, see: https://docs.nestjs.com/faq/common-errors at Injector.lookupComponentInParentModules (/Users/smaclapotop-28/githubspyne/market-anlayzer/node_modules/@nestjs/core/injector/injector.js:286:19) at process.processTicksAndRejections (node:internal/process/task_queues:105:5) at async resolveParam (/Users/smaclapotop-28/githubspyne/market-anlayzer/node_modules/@nestjs/core/injector/injector.js:141:38) at async Promise.all (index 3) at async Injector.resolveConstructorParams (/Users/smaclapotop-28/githubspyne/market-anlayzer/node_modules/@nestjs/core/injector/injector.js:169:27) at async Injector.loadInstance (/Users/smaclapotop-28/githubspyne/market-anlayzer/node_modules/@nestjs/core/injector/injector.js:75:13) at async Injector.loadProvider (/Users/smaclapotop-28/githubspyne/market-anlayzer/node_modules/@nestjs/core/injector/injector.js:103:9) at async /Users/smaclapotop-28/githubspyne/market-anlayzer/node_modules/@nestjs/core/injector/instance-loader.js:56:13 at async Promise.all (index 3) at async InstanceLoader.createInstancesOfProviders (/Users/smaclapotop-28/githubspyne/market-anlayzer/node_modules/@nestjs/core/injector/instance-loader.js:55:9) { type: 'AppService', context: { index: 3, dependencies: [ [class MySQLDatabaseService], [class MongoDatabaseService], [class PromptService], [class StockService] ], name: [class StockService] }, metadata: { id: '3d077ecdcb79b4e6d62dd' }, moduleRef: { id: 'b64b8033453f217376b18' } }

GitHub Copilot: The error occurs because the StockService is not properly imported in the AppModule. Let's fix this by updating the module configurations:

  1. First, ensure your StockModule is properly configured:
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { StockService } from './stock.service';
import { Stock, StockSchema } from './schemas/stock.schema';

@Module({
  imports: [
    MongooseModule.forFeature([{ name: Stock.name, schema: StockSchema }])
  ],
  providers: [StockService],
  exports: [StockService]  // Make sure to export the service
})
export class StockModule {}
  1. Then update your AppModule to import all required modules:
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { MongooseModule } from '@nestjs/mongoose';
import { ScheduleModule } from '@nestjs/schedule';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { StockModule } from './stock/stock.module';
import { MySQLDatabaseModule } from './database/mysql/mysql.module';
import { MongoDatabaseModule } from './database/mongo/mongo.module';
import { PromptModule } from './prompt/prompt.module';

@Module({
  imports: [
    ConfigModule.forRoot(),
    MongooseModule.forRoot(process.env.MONGODB_URI),
    ScheduleModule.forRoot(),
    StockModule,
    MySQLDatabaseModule,
    MongoDatabaseModule,
    PromptModule
  ],
  controllers: [AppController],
  providers: [AppService]
})
export class AppModule {}
  1. Make sure all your service modules export their services:
@Module({
  providers: [MySQLDatabaseService],
  exports: [MySQLDatabaseService]
})
@Module({
  providers: [MongoDatabaseService],
  exports: [MongoDatabaseService]
})
@Module({
  providers: [PromptService],
  exports: [PromptService]
})

This will:

  • Properly export all services
  • Import all required modules in AppModule
  • Set up dependency injection correctly
  • Resolve the unknown dependencies error

Make sure you have all environment variables set up in your .env file:

MONGODB_URI=mongodb://localhost:27017/market_analyzer

rakeshsharmaspyne: Error creating stock: Error: Stock validation failed: symbol: Path symbol is required. at ValidationError.inspect (/Users/smaclapotop-28/githubspyne/market-anlayzer/node_modules/mongoose/lib/error/validation.js:52:26) at formatValue (node:internal/util/inspect:877:19) at inspect (node:internal/util/inspect:404:10) at formatWithOptionsInternal (node:internal/util/inspect:2402:40) at formatWithOptions (node:internal/util/inspect:2264:10) at console.value (node:internal/console/constructor:336:14) at console.log (node:internal/console/constructor:384:61) at StockService.createStock (/Users/smaclapotop-28/githubspyne/market-anlayzer/src/stock/stock.service.ts:23:21) at process.processTicksAndRejections (node:internal/process/task_queues:105:5) at async AppService.handleCron (/Users/smaclapotop-28/githubspyne/market-anlayzer/src/app.service.ts:42:6) { errors: { symbol: ValidatorError: Path symbol is required. at validate (/Users/smaclapotop-28/githubspyne/market-anlayzer/node_modules/mongoose/lib/schemaType.js:1417:13) at SchemaType.doValidate (/Users/smaclapotop-28/githubspyne/market-anlayzer/node_modules/mongoose/lib/schemaType.js:1401:7) at /Users/smaclapotop-28/githubspyne/market-anlayzer/node_modules/mongoose/lib/document.js:3115:18 at process.processTicksAndRejections (node:internal/process/task_queues:85:11) { properties: [Object], kind: 'required', path: 'symbol', value: undefined, reason: undefined, Symbol(mongoose#validatorError): true } }, _message: 'Stock validation failed' }

GitHub Copilot: The error occurs because the symbol field is required in your Stock schema but it's not being provided when creating a new stock. Let's modify the AppService to ensure all required fields are included:

@Injectable()
export class AppService {
    // ...existing code...

    @Cron(CronExpression.EVERY_30_SECONDS)
    async handleCron() {
        try {
            const result = await this.mysqlDB.executeQuery(
                'SELECT name, symbol, sector FROM stock_cron_config WHERE is_active = 1 AND next_run_at <= NOW() LIMIT 1',
                []
            );

            if (!result || !result[0] || !result[0].symbol) {
                console.error('No valid stock data found or missing symbol');
                return;
            }

            const analysis = await this.promptService.analyzeStock(result[0].name);
            let responseText = analysis?.output?.[0]?.content?.[0]?.text;
            let cleanJson = responseText.replace(/```json\n|```/g, '');
            let jsonData = JSON.parse(cleanJson);

            const stockData = {
                stockName: result[0].name,
                stockSize: 'mid',
                stockDescription: jsonData?.Outlook?.Reasoning || 'No description available',
                symbol: result[0].symbol.toUpperCase(), // Ensure symbol is provided and uppercase
                exchange: 'NSE',
                currentPrice: jsonData?.PriceMetrics?.CurrentPrice || 0,
                changePercent: jsonData?.PriceMetrics?.DailyChangePercent || 0,
                volume: jsonData?.PriceMetrics?.Volume || 0,
                sector: result[0].sector || 'Unknown',
                isActive: true,
                lastUpdatedAt: new Date(),
                analysis: jsonData
            };

            console.log('Creating stock with data:', stockData);
            const savedStock = await this.stockService.createStock(stockData);
            console.log('Stock created successfully:', savedStock);

        } catch (error) {
            console.error('Analysis failed:', error);
        }
    }
}

Key changes made:

  1. Added validation for required fields
  2. Updated SQL query to explicitly select needed fields
  3. Added error handling for missing data
  4. Added logging to track data flow
  5. Ensured symbol is provided and uppercase
  6. Added default values for optional fields

Also, make sure your MySQL table has the correct columns:

CREATE TABLE `stock_cron_config` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  `frequency_minutes` int NOT NULL,
  `last_run_at` datetime DEFAULT NULL,
  `next_run_at` datetime GENERATED ALWAYS AS ((case when (`last_run_at` is not null) then (`last_run_at` + interval `frequency_minutes` minute) else NULL end)) STORED,
  `is_active` tinyint(1) DEFAULT '1',
  `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
)

rakeshsharmaspyne: optimize app.service.ts code

GitHub Copilot: ````typescript import { Injectable, Logger } from '@nestjs/common'; import { Cron, CronExpression } from '@nestjs/schedule'; import { MySQLDatabaseService } from './database/mysql/mysql.service'; import { MongoDatabaseService } from './database/mongo/mongo.service'; import { PromptService } from './prompt/prompt.service'; import { StockService } from './stock/stock.service';

@Injectable() export class AppService { private readonly logger = new Logger(AppService.name);

constructor( private readonly mysqlDB: MySQLDatabaseService, private readonly mongoDB: MongoDatabaseService, private readonly promptService: PromptService, private readonly stockService: StockService ) {}

getHello(): string { return 'Hello World!'; }

private safeParseAnalysis(text: string): any | null { if (!text) return null; try { const clean = text.replace(/json\n|/g, ''); return JSON.parse(clean); } catch (err) { this.logger.warn('Failed to parse analysis JSON', err as any); return null; } }

private buildStockPayload(row: any, jsonData: any) { return { stockName: row.name, stockSize: 'mid', stockDescription: jsonData?.Outlook?.Reasoning || 'No description available', symbol: (row.symbol || row.symbolName || '').toUpperCase(), exchange: row.exchange || 'NSE', currentPrice: jsonData?.PriceMetrics?.CurrentPrice || 0, changePercent: jsonData?.PriceMetrics?.DailyChangePercent || 0, volume: jsonData?.PriceMetrics?.Volume || 0, sector: row.sector || jsonData?.Sector || 'Unknown', isActive: true, lastUpdatedAt: new Date(), analysis: jsonData || {} }; }

@Cron(CronExpression.EVERY_30_SECONDS) async handleCron(): Promise { try { const rows = await this.mysqlDB.executeQuery( SELECT name, symbol, sector, IFNULL(exchange, 'NSE') as exchange FROM stock_cron_config WHERE is_active = 1 AND next_run_at <= NOW() LIMIT 10, [] );

  if (!rows || rows.length === 0) {
    this.logger.debug('No stocks to process');
    return;
  }

  await Promise.all(
    rows.map(async (row: any) => {
      if (!row?.symbol) {
        this.logger.warn(`Skipping row with missing symbol: ${JSON.stringify(row)}`);
        return;
      }

      try {
        const analysisResp = await this.promptService.analyzeStock(row.name);
        const responseText = analysisResp?.output?.[0]?.content?.[0]?.text;
        const jsonData = this.safeParseAnalysis(responseText);

        if (!jsonData) {
          this.logger.warn(`No valid analysis for ${row.name}`);
          return;
        }

        const payload = this.buildStockPayload(row, jsonData);
        const saved = await this.stockService.createStock(payload);
        if (saved) {
          this.logger.log(`Saved analysis for ${payload.symbol}`);
        } else {
          this.logger.error(`Failed to save stock for ${payload.symbol}`);
        }
      } catch (err) {
        this.logger.error(`Error processing stock ${row.name}`, err as any);
      }
    })
  );
} catch (error) {
  this.logger.error('handleCron failed', error as any);
}

}

@Cron(CronExpression.EVERY_DAY_AT_MIDNIGHT) async dailyStockAnalysis(): Promise { try { const analysisResp = await this.promptService.dailyStockAnalysis(); const responseText = analysisResp?.output?.[0]?.content?.[0]?.text; const jsonData = this.safeParseAnalysis(responseText); if (!jsonData) { this.logger.warn('dailyStockAnalysis returned invalid JSON'); return; }

  const payload = {
    stockName: jsonData.StockName || 'Unknown',
    stockSize: 'mid',
    stockDescription: jsonData?.Outlook?.Reasoning || 'No description available',
    symbol: (jsonData?.Symbol || jsonData?.StockName || '').toUpperCase(),
    exchange: 'NSE',
    currentPrice: jsonData?.PriceMetrics?.CurrentPrice || 0,
    changePercent: jsonData?.PriceMetrics?.DailyChangePercent || 0,
    volume: jsonData?.PriceMetrics?.Volume || 0,
    sector: jsonData?.Sector || 'Unknown',
    isActive: true,
    lastUpdatedAt: new Date(),
    analysis: jsonData
  };

  const saved = await this.stockService.createStock(payload);
  if (saved) this.logger.log(`dailyStockAnalysis saved ${payload.symbol}`);
} catch (error) {
  this.logger.error('dailyStockAnalysis failed', error as any);
}

} }


rakeshsharmaspyne: i am getting multiple stocks in
jsonData.Stocks
i want to bulk push in stockservice.createStock

jsonData.Stocks

GitHub Copilot: ````typescript
// ...existing code...
import { Injectable, Logger } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { Stock } from './schemas/stock.schema'
import { v4 as uuidv4 } from 'uuid';

@Injectable()
export class StockService {
  private readonly logger = new Logger(StockService.name);

  constructor(
    @InjectModel(Stock.name) private stockModel: Model<Stock>
  ) {}

  async createStock(body): Promise<Stock | null> {
    const stockId = uuidv4();
    try {
      const stock = new this.stockModel({ ...body, stockId });
      const savedStock = await stock.save();
      // this.logger.log(`Successfully created stock with ID: ${savedStock.id}`);
      return savedStock;
    } catch (error) {
      this.logger.error('Error creating stock:', error);
      return null;
    }
  }

  // Added bulk insert method
  async createStocksBulk(bodies: Partial<Stock>[]): Promise<{ insertedCount: number; insertedDocs: any[]; errors?: any[] }> {
    if (!Array.isArray(bodies) || bodies.length === 0) {
      return { insertedCount: 0, insertedDocs: [] };
    }

    const docs = bodies.map(b => ({
      stockId: b.stockId || uuidv4(),
      stockName: b.stockName,
      stockSize: b.stockSize || 'mid',
      stockDescription: b.stockDescription || b?.analysis?.Outlook?.Reasoning || 'No description available',
      symbol: (b.symbol || b.stockName || '').toUpperCase(),
      exchange: b.exchange || 'NSE',
      currentPrice: (b.currentPrice ?? 0),
      changePercent: (b.changePercent ?? 0),
      volume: (b.volume ?? 0),
      sector: b.sector || 'Unknown',
      isActive: (typeof b.isActive === 'boolean') ? b.isActive : true,
      lastUpdatedAt: b.lastUpdatedAt || new Date(),
      analysis: b.analysis || {}
    }));

    try {
      const inserted = await this.stockModel.insertMany(docs, { ordered: false });
      return { insertedCount: inserted.length, insertedDocs: inserted };
    } catch (err: any) {
      // insertMany may throw on duplicates; it may still have insertedDocs / writeErrors
      const insertedDocs = err?.insertedDocs ?? err?.result?.insertedIds ?? [];
      const writeErrors = err?.writeErrors ?? [err];
      this.logger.warn('Bulk insert had errors, partial success', writeErrors);
      return { insertedCount: Array.isArray(insertedDocs) ? insertedDocs.length : 0, insertedDocs: insertedDocs, errors: writeErrors };
    }
  }
}
// ...existing code...
// ...existing code...
  @Cron(CronExpression.EVERY_30_SECONDS)
  async handleCron(): Promise<void> {
    try {
      const rows = await this.mysqlDB.executeQuery(
        `SELECT name, symbol, sector, IFNULL(exchange, 'NSE') as exchange
         FROM stock_cron_config
         WHERE is_active = 1 AND next_run_at <= NOW()
         LIMIT 10`,
        []
      );

      if (!rows || rows.length === 0) {
        this.logger.debug('No stocks to process');
        return;
      }

      await Promise.all(
        rows.map(async (row: any) => {
          if (!row?.symbol) {
            this.logger.warn(`Skipping row with missing symbol: ${JSON.stringify(row)}`);
            return;
          }

          try {
            const analysisResp = await this.promptService.analyzeStock(row.name);
            const responseText = analysisResp?.output?.[0]?.content?.[0]?.text;
            const jsonData = this.safeParseAnalysis(responseText);

            if (!jsonData) {
              this.logger.warn(`No valid analysis for ${row.name}`);
              return;
            }

            // If analysis contains multiple stocks, bulk insert them
            if (Array.isArray(jsonData.Stocks) && jsonData.Stocks.length > 0) {
              const payloads = jsonData.Stocks.map((s: any) => ({
                stockName: s['Stock Name'] || s.StockName || row.name,
                stockSize: s.stockSize || 'mid',
                stockDescription: s.stockDescription || s?.Outlook?.Reasoning || 'No description available',
                symbol: (s.Symbol || s.symbol || s['Stock Name'] || row.symbol).toUpperCase(),
                exchange: s.Exchange || row.exchange || 'NSE',
                currentPrice: s?.PriceMetrics?.CurrentPrice || 0,
                changePercent: s?.PriceMetrics?.DailyChangePercent || 0,
                volume: s?.PriceMetrics?.Volume || 0,
                sector: s.Sector || row.sector || 'Unknown',
                isActive: true,
                lastUpdatedAt: new Date(),
                analysis: s
              }));

              const result = await this.stockService.createStocksBulk(payloads);
              this.logger.log(`Bulk insert result for ${row.symbol}: inserted ${result.insertedCount}`);
            } else {
              // Single stock fallback (existing flow)
              const payload = this.buildStockPayload(row, jsonData);
              const saved = await this.stockService.createStock(payload);
              if (saved) {
                this.logger.log(`Saved analysis for ${payload.symbol}`);
              } else {
                this.logger.error(`Failed to save stock for ${payload.symbol}`);
              }
            }
          } catch (err) {
            this.logger.error(`Error processing stock ${row.name}`, err as any);
          }
        })
      );
    } catch (error) {
      this.logger.error('handleCron failed', error as any);
    }
  }
// ...existing code...

Notes:

  • Added StockService.createStocksBulk using insertMany with ordered: false to continue on duplicates.
  • AppService now checks jsonData.Stocks and prepares payloads to call createStocksBulk.
  • Payload mapping ensures required fields (symbol, stockName, currentPrice, etc.) are present/defaulted.
  • Logs partial successes and errors; adjust according to your deduplication/upsert needs.

rakeshsharmaspyne: i have create process.env.DB_HOST but .env is not used why

GitHub Copilot: To use environment variables from .env file in NestJS, you need to set up the ConfigModule. Here's how to fix it:

  1. First, install the config package if not already installed:
npm install @nestjs/config
  1. Update your MySQL module to use ConfigModule and ConfigService:
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { MySQLDatabaseService } from './mysql.service';

@Module({
  imports: [
    ConfigModule.forRoot(),
    TypeOrmModule.forRootAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (configService: ConfigService) => ({
        type: 'mysql',
        host: configService.get('DB_HOST') || 'localhost',
        port: configService.get('DB_PORT') || 3307,
        username: configService.get('DB_USERNAME') || 'root',
        password: configService.get('DB_PASSWORD') || '1234',
        database: configService.get('DB_NAME') || 'market_analyzer',
        entities: [],
        synchronize: true,
      }),
    }),
  ],
  providers: [MySQLDatabaseService],
  exports: [MySQLDatabaseService],
})
export class MySQLDatabaseModule {}
  1. Create or update your .env file in the project root:
DB_HOST=localhost
DB_PORT=3307
DB_USERNAME=root
DB_PASSWORD=1234
DB_NAME=market_analyzer
  1. Make sure .env is in your .gitignore:
# Environment variables
.env
.env.*
  1. Update your main AppModule to import ConfigModule globally:
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { MySQLDatabaseModule } from './database/mysql/mysql.module';

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
    }),
    MySQLDatabaseModule,
    // ...other modules
  ],
  // ...rest of module config
})
export class AppModule {}

These changes will:

  • Load environment variables from .env file
  • Make ConfigModule available globally
  • Use ConfigService to access environment variables
  • Provide type safety for configuration
  • Allow for different environments (development, production, etc.)

rakeshsharmaspyne: create readme file for this project

GitHub Copilot: # Market Analyzer

A NestJS application for analyzing stock market data using AI-powered insights and managing stock information across MySQL and MongoDB databases.

Features

  • Real-time stock analysis using OpenAI GPT
  • Dual database architecture (MySQL + MongoDB)
  • Automated data collection via cron jobs
  • REST API endpoints for stock data
  • Environment-based configuration
  • TypeScript support

Prerequisites

  • Node.js (v18 or later)
  • MySQL (v8.0 or later)
  • MongoDB (v6.0 or later)
  • OpenAI API key

Installation

# Clone the repository
git clone <repository-url>
cd market-analyzer

# Install dependencies
npm install

Configuration

Create a .env file in the project root:

# Database Configuration
DB_HOST=localhost
DB_PORT=3307
DB_USERNAME=root
DB_PASSWORD=your_password
DB_NAME=market_analyzer

# MongoDB Configuration
MONGODB_URI=mongodb://localhost:27017/market_analyzer

# OpenAI Configuration
OPENAI_API_KEY=your_openai_api_key

Database Setup

-- Create MySQL database and tables
CREATE DATABASE IF NOT EXISTS market_analyzer;
USE market_analyzer;

CREATE TABLE `stock_cron_config` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  `frequency_minutes` int NOT NULL,
  `last_run_at` datetime DEFAULT NULL,
  `next_run_at` datetime GENERATED ALWAYS AS ((case when (`last_run_at` is not null) then (`last_run_at` + interval `frequency_minutes` minute) else NULL end)) STORED,
  `is_active` tinyint(1) DEFAULT '1',
  `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
)

Running the Application

# Development mode
npm run start:dev

# Production mode
npm run build
npm run start:prod

Docker Support

# Build Docker image
docker build -t market-analyzer:1.0 .

# Run container
docker run -d -p 3000:3000 --name market-analyzer market-analyzer:1.0

Project Structure

market-analyzer/
├── src/
│   ├── app.module.ts
│   ├── app.service.ts
│   ├── database/
│   │   ├── mysql/
│   │   └── mongo/
│   ├── stock/
│   │   ├── schemas/
│   │   └── services/
│   └── prompt/
├── test/
├── Dockerfile
└── package.json

API Documentation

Stock Analysis Endpoints

GET /api/stocks              // Get all stocks
POST /api/stocks            // Create new stock
GET /api/stocks/:symbol     // Get stock by symbol

Cron Jobs

  • EVERY_30_SECONDS: Fetches and analyzes configured stocks
  • EVERY_3_HOURS: Updates stock data
  • EVERY_DAY_AT_MIDNIGHT: Performs daily analysis

Testing

# Unit tests
npm run test

# E2E tests
npm run test:e2e

Environment Variables

Variable Description Default
DB_HOST MySQL host localhost
DB_PORT MySQL port 3307
DB_USERNAME MySQL username root
DB_PASSWORD MySQL password -
DB_NAME MySQL database name market_analyzer
MONGODB_URI MongoDB connection URI mongodb://localhost:27017/market_analyzer
OPENAI_API_KEY OpenAI API key -

Contributing

  1. Fork the repository
  2. Create your feature branch
  3. Commit your changes
  4. Push to the branch
  5. Create a new Pull Request

License

MIT License

Support

For support, please open an issue in the repository.

rakeshsharmaspyne: create readme file and push into it

GitHub Copilot: # Market Analyzer - AI-Powered Stock Analysis

Overview

Real-time stock market analysis using NestJS, OpenAI GPT, and dual database architecture (MySQL + MongoDB).

Tech Stack

  • NestJS (v10+)
  • MySQL v8.0
  • MongoDB v6.0
  • OpenAI GPT-4
  • TypeScript
  • Docker

Quick Start

Install Dependencies

npm install

Configure Environment

Create .env file:

# Database
DB_HOST=localhost
DB_PORT=3307
DB_USERNAME=root
DB_PASSWORD=your_password
DB_NAME=market_analyzer

# MongoDB
MONGODB_URI=mongodb://localhost:27017/market_analyzer

# OpenAI
OPENAI_API_KEY=your_api_key

Database Setup

CREATE DATABASE IF NOT EXISTS market_analyzer;
USE market_analyzer;

CREATE TABLE `stock_cron_config` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  `frequency_minutes` int NOT NULL,
  `last_run_at` datetime DEFAULT NULL,
  `next_run_at` datetime GENERATED ALWAYS AS ((case when (`last_run_at` is not null) then (`last_run_at` + interval `frequency_minutes` minute) else NULL end)) STORED,
  `is_active` tinyint(1) DEFAULT '1',
  `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
)

Run Application

# Development
npm run start:dev

# Production
npm run build
npm run start:prod

Docker Support

# Build
docker build -t market-analyzer:1.0 .

# Run
docker run -d -p 3000:3000 market-analyzer:1.0

Architecture

Directory Structure

market-analyzer/
├── src/
│   ├── app.module.ts          # Main application module
│   ├── database/             # Database connections
│   │   ├── mysql/
│   │   └── mongo/
│   ├── stock/               # Stock analysis
│   │   ├── schemas/
│   │   └── services/
│   └── prompt/              # OpenAI integration
├── test/
└── docker/

Features

  • Real-time stock analysis
  • Automated data collection (cron)
  • Dual database architecture
  • REST API endpoints
  • Docker support
  • Environment-based config

Cron Jobs

  • Every 30s: Stock analysis
  • Every 3h: Data updates
  • Daily: Market summary

API Routes

Stocks

GET    /api/stocks          // List stocks
POST   /api/stocks          // Create stock
GET    /api/stocks/:symbol  // Get by symbol

Development

Prerequisites

  • Node.js v18+
  • MySQL v8.0+
  • MongoDB v6.0+
  • OpenAI API access

Testing

# Unit tests
npm run test

# E2E tests
npm run test:e2e

Environment Variables

Variable Description Default
DB_HOST MySQL host localhost
DB_PORT MySQL port 3307
DB_USERNAME MySQL username root
DB_PASSWORD MySQL password -
DB_NAME Database name market_analyzer
MONGODB_URI MongoDB URI mongodb://localhost:27017/market_analyzer
OPENAI_API_KEY OpenAI key -

Contributing

  1. Fork repository
  2. Create feature branch
  3. Commit changes
  4. Push to branch
  5. Create Pull Request

License

MIT

Support

Open an issue in repository for support.

Save this content in a file named README.md in your project root:

# Market Analyzer - AI-Powered Stock Analysis

[Rest of the content from above...]

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published