new

package simplex.bn25.makino335926.trading.position;

import java.math.BigDecimal;

/**
 * クラス: Position
 * 銘柄ごとのポジションデータを管理するクラス。
 * 保有数量が0(クローズ)になった場合、平均取得単価をリセットする処理を追加。
 */
public class Position {

    private final String ticker;          // 銘柄コード
    private final String name;            // 銘柄名
    private long quantity;                // 保有数量
    private BigDecimal averageUnitPrice;  // 平均取得単価
    private BigDecimal realizedPnL;       // 実現損益
    private BigDecimal valuation;         // 評価額
    private BigDecimal unrealizedPnL;     // 評価損益

    /**
     * コンストラクタ
     * 初期状態では保有数量、単価、損益をすべてゼロまたは初期値で設定。
     * 
     * @param ticker 銘柄コード
     * @param name   銘柄名
     */
    public Position(String ticker, String name) {
        this.ticker = ticker;
        this.name = name;
        this.quantity = 0;
        this.averageUnitPrice = BigDecimal.ZERO;
        this.realizedPnL = BigDecimal.ZERO;
        this.valuation = null;
        this.unrealizedPnL = null;
    }

    // Getterメソッド: 保有データや計算済みデータを取得
    public String getTicker() { return ticker; }
    public String getName() { return name; }
    public long getQuantity() { return quantity; }
    public BigDecimal getAverageUnitPrice() { return averageUnitPrice; }
    public BigDecimal getRealizedPnL() { return realizedPnL; }
    public BigDecimal getValuation() { return valuation; }
    public BigDecimal getUnrealizedPnL() { return unrealizedPnL; }

    /**
     * メソッド: updateQuantity
     * 保有数量を増減し、数量が0になった場合は平均取得単価をリセット。
     *
     * @param delta 増減分(買いなら正、売りなら負)
     */
    public void updateQuantity(long delta) {
        this.quantity += delta; // 保有数量を更新

        if (this.quantity == 0) {
            // 保有数量が0の場合、ポジションはクローズされたとみなし、平均取得単価をリセット
            this.averageUnitPrice = BigDecimal.ZERO;
        }
    }

    /**
     * メソッド: updateAverageUnitPrice
     * 新たな購入単価を基に加重平均を計算し、平均取得単価を更新。
     * 保有数量が0の場合、単価をリセット。
     *
     * @param newPrice     新たに購入した株式の単価
     * @param deltaQuantity 新たに購入した株式の数量
     */
    public void updateAverageUnitPrice(BigDecimal newPrice, long deltaQuantity) {
        BigDecimal totalCost = this.averageUnitPrice.multiply(BigDecimal.valueOf(this.quantity))
                .add(newPrice.multiply(BigDecimal.valueOf(deltaQuantity)));

        this.quantity += deltaQuantity;

        if (this.quantity > 0) {
            this.averageUnitPrice = totalCost.divide(BigDecimal.valueOf(this.quantity), 2, BigDecimal.ROUND_HALF_UP);
        } else {
            // 保有数量が0の場合、平均取得単価をリセット
            this.averageUnitPrice = BigDecimal.ZERO;
        }
    }

    /**
     * メソッド: addRealizedPnL
     * 実現損益を累積更新。
     *
     * @param amount 売却取引で得た損益額
     */
    public void addRealizedPnL(BigDecimal amount) {
        this.realizedPnL = this.realizedPnL.add(amount);
    }

    /**
     * メソッド: setValuation
     * 保有数量と時価データに基づき、評価額と評価損益を計算。
     *
     * @param marketPrice 現在の時価
     */
    public void setValuation(BigDecimal marketPrice) {
        if (marketPrice != null) {
            this.valuation = marketPrice.multiply(BigDecimal.valueOf(this.quantity));
            this.unrealizedPnL = this.valuation.subtract(this.averageUnitPrice.multiply(BigDecimal.valueOf(this.quantity)));
        } else {
            this.valuation = null;
            this.unrealizedPnL = null;
        }
    }
}

コメント

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