From 8834c1c1b10aeaaecd27ed2ec1d6fb7ab3128fb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sven=20G=C3=BCnther?= Date: Mon, 9 Feb 2026 15:41:42 +0100 Subject: [PATCH] fix minor issues from feedback --- CHANGELOG.md | 10 +- CLAUDE.md | 119 ------------------ .../calculator/portfolio-calculator.ts | 4 +- .../roai/portfolio-calculator-cash.spec.ts | 2 +- ...-calculator-msft-buy-with-dividend.spec.ts | 3 +- .../calculator/roai/portfolio-calculator.ts | 2 +- .../src/app/portfolio/portfolio.service.ts | 4 +- .../interfaces/portfolio-summary.interface.ts | 2 +- .../src/lib/models/portfolio-snapshot.ts | 3 +- .../src/lib/models/timeline-position.ts | 3 +- 10 files changed, 18 insertions(+), 134 deletions(-) delete mode 100644 CLAUDE.md diff --git a/CHANGELOG.md b/CHANGELOG.md index f264473e4..fa8cd79e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Added + +- Added the dividend yield (trailing twelve months) to the portfolio summary (experimental) + ## 2.237.0 - 2026-02-08 ### Changed @@ -48,10 +54,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## 2.234.0 - 2026-01-30 -### Added - -- Added the annualized dividend yield to the portfolio summary (experimental) - ### Changed - Improved the usability of the create asset profile dialog in the market data section of the admin control panel diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 8ea8b51a0..000000000 --- a/CLAUDE.md +++ /dev/null @@ -1,119 +0,0 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## Project Overview - -Ghostfolio is an open source wealth management software built with TypeScript in an Nx monorepo workspace. It's a full-stack application with Angular frontend and NestJS backend, using PostgreSQL with Prisma ORM and Redis for caching. - -## Development Commands - -### Environment Setup - -```bash -npm install -docker compose -f docker/docker-compose.dev.yml up -d # Start PostgreSQL and Redis -npm run database:setup # Initialize database schema -``` - -### Development Servers - -```bash -npm run start:server # Start NestJS API server -npm run start:client # Start Angular client (English) -npm run watch:server # Start server in watch mode for debugging -``` - -### Build and Production - -```bash -npm run build:production # Build both API and client for production -npm run start:production # Run production build with database migration -``` - -### Database Operations - -```bash -npm run database:push # Sync schema with database (development) -npm run database:migrate # Apply migrations (production) -npm run database:seed # Seed database with initial data -npm run database:gui # Open Prisma Studio -npm run database:format-schema # Format Prisma schema -npm run database:generate-typings # Generate Prisma client -``` - -### Testing and Quality - -```bash -npm test # Run all tests (API + common) -npm run test:api # Run API tests only -npm run test:common # Run common library tests -npm run test:single # Run single test file (example provided) -npm run lint # Run ESLint on all projects -npm run format # Format code with Prettier -npm run format:check # Check code formatting -``` - -### Nx Workspace Commands - -```bash -nx affected:build # Build affected projects -nx affected:test # Test affected projects -nx affected:lint # Lint affected projects -nx dep-graph # View dependency graph -``` - -### Storybook (Component Library) - -```bash -npm run start:storybook # Start Storybook development server -npm run build:storybook # Build Storybook for production -``` - -## Architecture - -### Monorepo Structure - -- **apps/api**: NestJS backend application -- **apps/client**: Angular frontend application -- **apps/client-e2e**: E2E tests for client -- **apps/ui-e2e**: E2E tests for UI components -- **libs/common**: Shared TypeScript libraries and utilities -- **libs/ui**: Angular UI component library - -### Technology Stack - -- **Frontend**: Angular 20 with Angular Material, Bootstrap utility classes -- **Backend**: NestJS with TypeScript -- **Database**: PostgreSQL with Prisma ORM -- **Caching**: Redis with Bull for job queues -- **Build Tool**: Nx workspace -- **Testing**: Jest for unit tests, Cypress for E2E tests - -### Key Dependencies - -- **Authentication**: Passport (JWT, Google OAuth, WebAuthn) -- **Data Sources**: Yahoo Finance, CoinGecko APIs for market data -- **Charts**: Chart.js with various plugins -- **Payment**: Stripe integration -- **Internationalization**: Angular i18n with multiple language support - -### Database Schema - -The Prisma schema defines models for: - -- User management and access control -- Account and portfolio tracking -- Trading activities and orders -- Market data and asset information -- Platform integrations - -### Development Notes - -- Node.js version >=22.18.0 required -- Uses Nx generators for consistent code scaffolding -- Husky for git hooks and code quality enforcement -- Environment files: `.env.dev` for development, `.env.example` as template -- SSL certificates can be generated for localhost development -- Experimental features can be toggled via user settings -- always run the .husky pre commit hooks after code changes diff --git a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts index 67a21ab33..dc1a0d5ff 100644 --- a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts @@ -188,9 +188,9 @@ export abstract class PortfolioCalculator { if (!transactionPoints.length) { return { activitiesCount: 0, - dividendYieldTrailingTwelveMonths: 0, createdAt: new Date(), currentValueInBaseCurrency: new Big(0), + dividendYieldTrailingTwelveMonths: 0, errors: [], hasErrors: false, historicalData: [], @@ -439,11 +439,11 @@ export abstract class PortfolioCalculator { : 0; positions.push({ + dividendYieldTrailingTwelveMonths, includeInTotalAssetValue, timeWeightedInvestment, timeWeightedInvestmentWithCurrencyEffect, activitiesCount: item.activitiesCount, - dividendYieldTrailingTwelveMonths, averagePrice: item.averagePrice, currency: item.currency, dataSource: item.dataSource, diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-cash.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-cash.spec.ts index d9cb4f808..9873771f0 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-cash.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-cash.spec.ts @@ -231,13 +231,13 @@ describe('PortfolioCalculator', () => { */ expect(position).toMatchObject({ activitiesCount: 2, - dividendYieldTrailingTwelveMonths: 0, averagePrice: new Big(1), currency: 'USD', dataSource: DataSource.YAHOO, dateOfFirstActivity: '2023-12-31', dividend: new Big(0), dividendInBaseCurrency: new Big(0), + dividendYieldTrailingTwelveMonths: 0, fee: new Big(0), feeInBaseCurrency: new Big(0), grossPerformance: new Big(0), diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-msft-buy-with-dividend.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-msft-buy-with-dividend.spec.ts index e82f9ee4f..2325d2087 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-msft-buy-with-dividend.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-msft-buy-with-dividend.spec.ts @@ -289,8 +289,7 @@ describe('PortfolioCalculator', () => { fee: new Big('19'), quantity: new Big('1'), symbol: 'MSFT', - tags: [], - transactionCount: 5 + tags: [] } ], totalFeesWithCurrencyEffect: new Big('19'), diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts index b20200766..bc534ca16 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts @@ -125,6 +125,7 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator { return { currentValueInBaseCurrency, + dividendYieldTrailingTwelveMonths, hasErrors, positions, totalFeesWithCurrencyEffect, @@ -134,7 +135,6 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator { activitiesCount: this.activities.filter(({ type }) => { return ['BUY', 'SELL'].includes(type); }).length, - dividendYieldTrailingTwelveMonths, createdAt: new Date(), errors: [], historicalData: [], diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index a288dc60f..96b98eaa0 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -1861,8 +1861,8 @@ export class PortfolioService { } const { - dividendYieldTrailingTwelveMonths, currentValueInBaseCurrency, + dividendYieldTrailingTwelveMonths, totalInvestment } = await portfolioCalculator.getSnapshot(); @@ -1962,11 +1962,11 @@ export class PortfolioService { })?.toNumber(); return { - dividendYieldTrailingTwelveMonths, annualizedPerformancePercent, annualizedPerformancePercentWithCurrencyEffect, cash, dateOfFirstActivity, + dividendYieldTrailingTwelveMonths, excludedAccountsAndActivities, netPerformance, netPerformancePercentage, diff --git a/libs/common/src/lib/interfaces/portfolio-summary.interface.ts b/libs/common/src/lib/interfaces/portfolio-summary.interface.ts index 532870791..82a7ae6ae 100644 --- a/libs/common/src/lib/interfaces/portfolio-summary.interface.ts +++ b/libs/common/src/lib/interfaces/portfolio-summary.interface.ts @@ -3,13 +3,13 @@ import { PortfolioPerformance } from './portfolio-performance.interface'; export interface PortfolioSummary extends PortfolioPerformance { activityCount: number; - dividendYieldTrailingTwelveMonths: number; annualizedPerformancePercent: number; annualizedPerformancePercentWithCurrencyEffect: number; cash: number; committedFunds: number; dateOfFirstActivity: Date; dividendInBaseCurrency: number; + dividendYieldTrailingTwelveMonths: number; emergencyFund: { assets: number; cash: number; diff --git a/libs/common/src/lib/models/portfolio-snapshot.ts b/libs/common/src/lib/models/portfolio-snapshot.ts index 33bab356c..968d2a565 100644 --- a/libs/common/src/lib/models/portfolio-snapshot.ts +++ b/libs/common/src/lib/models/portfolio-snapshot.ts @@ -10,7 +10,6 @@ import { Transform, Type } from 'class-transformer'; export class PortfolioSnapshot { activitiesCount: number; - dividendYieldTrailingTwelveMonths: number; createdAt: Date; @@ -18,6 +17,8 @@ export class PortfolioSnapshot { @Type(() => Big) currentValueInBaseCurrency: Big; + dividendYieldTrailingTwelveMonths: number; + errors: AssetProfileIdentifier[]; hasErrors: boolean; diff --git a/libs/common/src/lib/models/timeline-position.ts b/libs/common/src/lib/models/timeline-position.ts index ba4a93482..6426c3392 100644 --- a/libs/common/src/lib/models/timeline-position.ts +++ b/libs/common/src/lib/models/timeline-position.ts @@ -10,7 +10,6 @@ import { Transform, Type } from 'class-transformer'; export class TimelinePosition { activitiesCount: number; - dividendYieldTrailingTwelveMonths: number; @Transform(transformToBig, { toClassOnly: true }) @Type(() => Big) @@ -28,6 +27,8 @@ export class TimelinePosition { @Type(() => Big) dividendInBaseCurrency: Big; + dividendYieldTrailingTwelveMonths: number; + @Transform(transformToBig, { toClassOnly: true }) @Type(() => Big) fee: Big;