DR一個前の投稿の修正箇所を改善

package simplex.bn25.datemasa335859.trading.a;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

public class MarketPriceLoader {
    private static final String MARKET_PRICE_FILE_PATH = "trading-app/src/market_price.csv"; // 時価データのCSVファイルパス
    private static final Map<String, BigDecimal> MARKET_PRICES = new HashMap<>(); // 銘柄コードと時価のマッピング

    // CSVファイルから時価データを読み込むメソッド
    public static void loadMarketPrices() {
        try (BufferedReader br = new BufferedReader(new FileReader(MARKET_PRICE_FILE_PATH))) {
            MARKET_PRICES.clear(); // 既存の時価データをクリアして再読み込み
            String line;

            // ヘッダー行をスキップ
            br.readLine();

            while ((line = br.readLine()) != null) {
                String[] data = line.split(","); // CSVをカンマで分割
                if (data.length == 2) { // 列数が2であることを確認
                    String ticker = data[0].trim(); // 銘柄コードを取得
                    String priceString = data[1].trim(); // 時価を取得

                    if (isValidNumber(priceString)) { // 有効な数値かを確認
                        try {
                            BigDecimal price = new BigDecimal(priceString); // 有効な場合のみBigDecimalを作成
                            MARKET_PRICES.put(ticker, price); // マップに保存
                        } catch (NumberFormatException e) {
                            System.out.println("エラー: 不正な時価データが検出されました。スキップします。行: " + line);
                        }
                    } else {
                        System.out.println("エラー: 不正な時価データが検出されました。スキップします。行: " + line);
                    }
                }
            }
        } catch (IOException e) {
            System.out.println("エラー: 時価データの読み込みに失敗しました。");
        }
    }

    // 銘柄コードに対応する時価を取得するメソッド
    public static BigDecimal getMarketPrice(String ticker) {
        return MARKET_PRICES.get(ticker); // 銘柄コードから時価を取得
    }

    // 入力文字列が有効な数値かどうかを確認するユーティリティメソッド
    private static boolean isValidNumber(String value) {
        try {
            new BigDecimal(value); // BigDecimalの作成を試みる
            return true; // 成功したら有効
        } catch (NumberFormatException e) {
            return false; // 数値として無効
        }
    }
}
package simplex.bn25.datemasa335859.trading.a;

import simplex.bn25.datemasa335859.trading.stock.TickerManager;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Map;

public class PositionCalculator {
    private final TradeDataLoader tradeDataLoader;

    // コンストラクタでTradeDataLoaderのインスタンスを受け取る
    public PositionCalculator(TradeDataLoader tradeDataLoader) {
        this.tradeDataLoader = tradeDataLoader;
    }

    // 保有ポジションを計算し、表示するメソッド
    public void displayPositions() {
        Map<String, Position> positions = tradeDataLoader.calculatePositions();

        if (positions.isEmpty()) {
            System.out.println("取引データが登録されていません。");
            return;
        }

        // 表のヘッダーを表示
        System.out.println("|===============================================================================================================|");
        System.out.println("| Ticker | Product Name                 | Quantity   | Avg Unit Price   | Realized PnL   | Valuation   | Unrealized PnL |");
        System.out.println("|--------+-------------------------------+------------+------------------+----------------+-------------+----------------|");

        // 各ポジションについて情報を表示
        for (Map.Entry<String, Position> entry : positions.entrySet()) {
            String ticker = entry.getKey();
            Position position = entry.getValue();

            // tickerNameの取得
            String tickerName = TickerManager.getTickerToNameMap().getOrDefault(ticker, "Unknown");

            // 時価情報を取得
            BigDecimal marketPrice = MarketPriceLoader.getMarketPrice(ticker);

            // 評価額を計算
            BigDecimal valuation = marketPrice != null
                    ? position.calculateValuation(marketPrice).setScale(2, RoundingMode.HALF_UP)
                    : null;

            // 評価損益を計算
            BigDecimal unrealizedPnL = marketPrice != null
                    ? position.calculateUnrealizedPnL(marketPrice).setScale(2, RoundingMode.HALF_UP)
                    : null;

            // 表形式で出力。時価がない場合は"N/A"を表示
            System.out.printf("| %-6s | %-29s | %10d | %,16.2f | %-14s | %-11s | %-14s |\n",
                    ticker,
                    tickerName,
                    position.quantity(),
                    position.getAverageUnitPrice(),
                    position.getRealizedPnL().compareTo(BigDecimal.ZERO) != 0 ? position.getRealizedPnL() : "N/A",
                    valuation != null ? valuation : "N/A",
                    unrealizedPnL != null ? unrealizedPnL : "N/A");
        }

        // 表のフッターを表示
        System.out.println("|===============================================================================================================|");
    }
}

下記は修正の必要かもしれないクラス

package simplex.bn25.datemasa335859.trading.stock;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class TickerManager {
    private static final String CSV_FILE_PATH = "trading-app/src/stocks.csv";
    private static final Set<String> EXISTING_TICKERS = new HashSet<>();
    private static final Map<String, String> TICKERS_TO_NAME_MAP = new HashMap<>();
    private static boolean isLoaded = false;

    // 初回のみ銘柄コードと銘柄名を読み込む
    public static void loadExistingTickers() {
        if (isLoaded) {
            return;
        }
        try (BufferedReader br = new BufferedReader(new FileReader(CSV_FILE_PATH))) {
            br.readLine(); // ヘッダー行をスキップ
            String line;
            while ((line = br.readLine()) != null) {
                String[] stockData = line.split(",");
                if (stockData.length >= 2) { // 銘柄コードと銘柄名の両方が存在する場合のみ追加
                    String ticker = stockData[0].trim();
                    String name = stockData[1].trim();
                    EXISTING_TICKERS.add(ticker);
                    TICKERS_TO_NAME_MAP.put(ticker, name);
                }
            }
            isLoaded = true;
        } catch (IOException e) {
            System.out.println("エラー: stocks.csv の読み込みに失敗しました。");
        }
    }

    // 有効なティッカーコードのセットを取得
    public static Set<String> getExistingTickers() {
        if (!isLoaded) {
            loadExistingTickers();
        }
        return EXISTING_TICKERS;
    }

    // 銘柄コードと銘柄名のマップを取得
    public static Map<String, String> getTickerToNameMap() {
        if (!isLoaded) {
            loadExistingTickers();
        }
        return TICKERS_TO_NAME_MAP;
    }

    public static void addTicker(String ticker) {
        EXISTING_TICKERS.add(ticker);
    }
}
public BigDecimal calculateValuation(BigDecimal marketPrice) {
    return marketPrice != null
            ? marketPrice.multiply(BigDecimal.valueOf(quantity)).setScale(2, RoundingMode.HALF_UP)
            : null;
}

public BigDecimal calculateUnrealizedPnL(BigDecimal marketPrice) {
    BigDecimal valuation = calculateValuation(marketPrice);
    if (valuation != null) {
        return valuation.subtract(averageUnitPrice.multiply(BigDecimal.valueOf(quantity)))
                .setScale(2, RoundingMode.HALF_UP);
    }
    return null;
}

コメント

タイトルとURLをコピーしました