import { InvestmentReadQueryDto, InvestmentResourceMetaDto, } from '../../../investment-resource.dto'; import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { Transform } from 'class-transformer'; import { IsIn, IsOptional, IsString, Matches, MaxLength, MinLength, } from 'class-validator'; import { MoneyDto } from '../../../../../common/money.dto'; import { PortfolioPositionDto } from '../../../portfolio/portfolio.api'; const MAX_INSTRUMENT_QUERY_LENGTH = 80; export class StockSearchQueryDto extends InvestmentReadQueryDto { @ApiProperty({ minLength: 2, maxLength: MAX_INSTRUMENT_QUERY_LENGTH }) @Transform(({ value }: { value: unknown }) => typeof value === 'string' ? value.trim() : value, ) @IsString() @MinLength(2) @MaxLength(MAX_INSTRUMENT_QUERY_LENGTH) declare query: string; } export class StockTickerParamsDto { @ApiProperty({ minLength: 1, maxLength: MAX_INSTRUMENT_QUERY_LENGTH, pattern: '^[A-Za-z0-9][A-Za-z0-9._@+-]*$', }) @IsString() @MinLength(1) @MaxLength(MAX_INSTRUMENT_QUERY_LENGTH) @Matches(/^[A-Za-z0-9][A-Za-z0-9._@+-]*$/) declare ticker: string; } export class StockCandlesQueryDto extends InvestmentReadQueryDto { @ApiPropertyOptional({ enum: ['month', 'halfYear', 'year', 'all'], default: 'month', }) @IsOptional() @IsIn(['month', 'halfYear', 'year', 'all']) period?: 'month' | 'halfYear' | 'year' | 'all'; } export class StockDto { @ApiProperty({ format: 'uuid' }) declare instrumentUid: string; @ApiProperty({ description: 'Unambiguous ticker URL segment, or the exact instrument UID.', }) declare slug: string; @ApiProperty() declare name: string; @ApiProperty({ type: String, nullable: true }) declare isin: string | null; @ApiProperty({ type: String, nullable: true }) declare classCode: string | null; @ApiProperty({ type: String, nullable: true }) declare realExchange: string | null; @ApiProperty({ type: Boolean, nullable: true }) declare apiTradeAvailable: boolean | null; @ApiProperty({ type: String, nullable: true }) declare ticker: string | null; @ApiProperty({ type: String, nullable: true }) declare logoName: string | null; @ApiProperty({ type: String, nullable: true }) declare currency: string | null; @ApiProperty({ type: String, nullable: true }) declare shareType: string | null; @ApiProperty({ type: String, nullable: true }) declare sector: string | null; @ApiProperty({ type: Number, nullable: true }) declare lot: number | null; @ApiProperty({ type: String, nullable: true, format: 'date-time' }) declare historyFrom: string | null; } export class StockSearchResultDto extends StockDto { @ApiProperty({ type: MoneyDto, nullable: true }) declare price: MoneyDto | null; @ApiProperty({ type: String, nullable: true, format: 'date-time' }) declare priceAt: string | null; } export class StockQuoteDto { @ApiProperty({ type: MoneyDto, nullable: true }) declare price: MoneyDto | null; @ApiProperty({ type: String, nullable: true, format: 'date-time' }) declare priceAt: string | null; @ApiProperty({ type: String, nullable: true }) declare tradingStatus: string | null; @ApiProperty({ type: MoneyDto, nullable: true }) declare change: MoneyDto | null; @ApiProperty({ type: String, nullable: true }) declare changePercent: string | null; @ApiProperty({ type: String, nullable: true, format: 'date' }) declare previousCloseDate: string | null; @ApiProperty({ type: MoneyDto, nullable: true }) declare previousClose: MoneyDto | null; @ApiProperty({ type: [String] }) declare unavailable: string[]; @ApiProperty({ format: 'date-time' }) declare observedAt: string; } export class StockCandleDto { @ApiProperty({ format: 'date-time' }) declare time: string; @ApiProperty() declare close: string; @ApiProperty() declare isComplete: boolean; } export class StockCandlesDto { @ApiProperty({ type: [StockCandleDto] }) declare candles: StockCandleDto[]; @ApiProperty({ type: String, nullable: true }) declare currency: string | null; @ApiProperty({ type: String, nullable: true, format: 'date-time' }) declare historyFrom: string | null; @ApiProperty({ format: 'date-time' }) declare observedAt: string; } export class StockPositionRowDto extends PortfolioPositionDto { @ApiProperty({ type: String, nullable: true }) declare returnPercent: string | null; } export class StockPositionDto { @ApiProperty() declare quantity: string; @ApiProperty({ type: MoneyDto, nullable: true }) declare currentValue: MoneyDto | null; @ApiProperty({ type: MoneyDto, nullable: true }) declare averagePurchasePrice: MoneyDto | null; @ApiProperty({ type: MoneyDto, nullable: true }) declare absoluteReturn: MoneyDto | null; @ApiProperty({ type: String, nullable: true }) declare returnPercent: string | null; @ApiProperty({ type: [StockPositionRowDto] }) declare accounts: StockPositionRowDto[]; @ApiProperty() declare isStale: boolean; @ApiProperty({ format: 'date-time' }) declare observedAt: string; } export class StockMetricDto { @ApiProperty() declare key: string; @ApiProperty() declare value: number; @ApiProperty({ enum: ['money', 'ratio', 'percent'] }) declare unit: 'money' | 'ratio' | 'percent'; @ApiProperty({ type: String, nullable: true }) declare currency: string | null; @ApiProperty({ type: String, nullable: true, enum: ['TTM', 'MRQ'] }) declare period: 'TTM' | 'MRQ' | null; } export class StockCompanyDto { @ApiProperty({ type: String, nullable: true }) declare description: string | null; @ApiProperty({ type: [StockMetricDto] }) declare metrics: StockMetricDto[]; @ApiProperty({ type: [String] }) declare unavailable: string[]; @ApiProperty({ format: 'date-time' }) declare observedAt: string; } export class StockDividendDto { @ApiProperty({ type: MoneyDto, nullable: true }) declare perShare: MoneyDto | null; @ApiProperty({ type: String, nullable: true, format: 'date' }) declare recordDate: string | null; @ApiProperty({ type: String, nullable: true, format: 'date' }) declare lastBuyDate: string | null; @ApiProperty({ type: String, nullable: true, format: 'date' }) declare paymentDate: string | null; @ApiProperty({ enum: ['upcoming', 'past', 'undated'] }) declare timing: 'upcoming' | 'past' | 'undated'; @ApiProperty({ type: MoneyDto, nullable: true }) declare estimatedAmount: MoneyDto | null; } export class StockDividendsDto { @ApiProperty({ type: [StockDividendDto] }) declare dividends: StockDividendDto[]; @ApiProperty({ format: 'date' }) declare from: string; @ApiProperty({ format: 'date' }) declare to: string; @ApiProperty({ format: 'date-time' }) declare observedAt: string; @ApiProperty({ type: String, nullable: true, format: 'date-time' }) declare positionAt: string | null; @ApiProperty() declare estimateUnavailable: boolean; @ApiProperty() declare positionIsStale: boolean; } export class StockPositionResourceDto { @ApiProperty({ type: StockPositionDto, nullable: true }) declare data: StockPositionDto | null; @ApiProperty({ type: InvestmentResourceMetaDto }) declare meta: InvestmentResourceMetaDto; } export class StockSearchResourceDto { @ApiProperty({ type: StockSearchResultDto, isArray: true, nullable: true }) declare data: StockSearchResultDto[] | null; @ApiProperty({ type: InvestmentResourceMetaDto }) declare meta: InvestmentResourceMetaDto; } export class StockResourceDto { @ApiProperty({ type: StockDto, nullable: true }) declare data: StockDto | null; @ApiProperty({ type: InvestmentResourceMetaDto }) declare meta: InvestmentResourceMetaDto; } export class StockQuoteResourceDto { @ApiProperty({ type: StockQuoteDto, nullable: true }) declare data: StockQuoteDto | null; @ApiProperty({ type: InvestmentResourceMetaDto }) declare meta: InvestmentResourceMetaDto; } export class StockCompanyResourceDto { @ApiProperty({ type: StockCompanyDto, nullable: true }) declare data: StockCompanyDto | null; @ApiProperty({ type: InvestmentResourceMetaDto }) declare meta: InvestmentResourceMetaDto; } export class StockCandlesResourceDto { @ApiProperty({ type: StockCandlesDto, nullable: true }) declare data: StockCandlesDto | null; @ApiProperty({ type: InvestmentResourceMetaDto }) declare meta: InvestmentResourceMetaDto; } export class StockDividendsResourceDto { @ApiProperty({ type: StockDividendsDto, nullable: true }) declare data: StockDividendsDto | null; @ApiProperty({ type: InvestmentResourceMetaDto }) declare meta: InvestmentResourceMetaDto; }