表示調整
閉じる
挿絵表示切替ボタン
▼配色
▼行間
▼文字サイズ
▼メニューバー
×閉じる

ブックマークに追加しました

設定
0/400
設定を保存しました
エラーが発生しました
※文字以内
ブックマークを解除しました。

エラーが発生しました。

エラーの原因がわからない場合はヘルプセンターをご確認ください。

ブックマーク機能を使うにはログインしてください。
step4  作者: Parmesan
1/10

完成 冬

import java.util.List;

import java.util.Scanner;


public class Main {

private static final String STOCKS_FILE = "stocks.csv";

private static final String TRADES_FILE = "trades.csv";

private static final String MARKET_VALUE_FILE = "marketValue.csv";


public static void main(String[] args) {

Scanner scanner = new Scanner(System.in);

HandleFile handleFile = new HandleFile();


System.out.println("株式取引管理システムを開始します。");

while (true) {

System.out.println("操作するメニューを選んでください。");

System.out.println("1.銘柄マスタ一覧表示");

System.out.println("2.銘柄マスタ新規登録");

System.out.println("3.取引入力");

System.out.println("4.取引一覧の表示");

System.out.println("5.保有ポジション表示");

System.out.println("9.アプリケーションを終了する");


boolean invalidInput = true;

while (invalidInput) {

System.out.print("入力してください:");

String userInput = scanner.nextLine();

switch (userInput) {

case "1":

System.out.println("銘柄マスタを表示します。");

List<Stock> stocks = handleFile.readStocksFromFile(STOCKS_FILE);

DisplayStocks displayStocks = new DisplayStocks(stocks);

displayStocks.displayStockList();

System.out.println("---");

invalidInput = false;

break;

case "2":

System.out.println("新規株式銘柄マスタを登録します。");

List<Stock> stocksForRegistration = handleFile.readStocksFromFile(STOCKS_FILE);

RegisterStock registerStock = new RegisterStock(stocksForRegistration, STOCKS_FILE);

registerStock.registerNewStocks();

System.out.println("---");

invalidInput = false;

break;

case "3":

System.out.println("取引入力を開始します。");

List<Stock> stocksForTrade = handleFile.readStocksFromFile(STOCKS_FILE);

RegisterTrade registerTrade = new RegisterTrade(stocksForTrade, TRADES_FILE);

registerTrade.registerTrade();

System.out.println("---");

invalidInput = false;

break;

case "4":

System.out.println("取引一覧を表示します。");

List<Trade> trades = handleFile.readTradesFromFile(TRADES_FILE);

DisplayTrades displayTrades = new DisplayTrades(trades);

displayTrades.displayTradeList();

System.out.println("---");

invalidInput = false;

break;

case "5":

System.out.println("保有ポジションを表示します。");


// データ読み込み

List<Trade> allTrades = handleFile.readTradesFromFile(TRADES_FILE);

List<MarketValue> marketValues = handleFile.readMarketValuesFromFile(MARKET_VALUE_FILE);


// 保有数量計算

CalculateQuantity calculateQuantity = new CalculateQuantity();

List<HoldingPosition> positions = calculateQuantity.calculateQuantity(allTrades);


CalculateAvgUnitPrice calculateAvgUnitPrice = new CalculateAvgUnitPrice();

List<HoldingPositionWithAveragePrice> positionsWithAvgPrice = calculateAvgUnitPrice.calculateAverageUnitPrice(allTrades);


OrganizePnL organizePnL = new OrganizePnL(positionsWithAvgPrice, marketValues);

List<HoldingPositionWithPnL> positionsWithPnL = organizePnL.organize(allTrades);


DisplayHoldingPosition displayHolding = new DisplayHoldingPosition(positionsWithPnL);

displayHolding.displayHoldingList();


break;

case "9":

System.out.println("アプリケーションを終了します。");

return;

default:

System.out.println("\"" + userInput + "\"に対応するメニューは存在しません。");

}

}

}

}

}


import java.math.BigDecimal;


public class HoldingPositionWithAveragePrice extends HoldingPosition {

private final BigDecimal averageUnitPrice;


public HoldingPositionWithAveragePrice(String ticker, String productName, long quantity, BigDecimal averageUnitPrice) {

super(ticker, productName, quantity);

this.averageUnitPrice = averageUnitPrice;

}


public BigDecimal getAverageUnitPrice() {

return averageUnitPrice;

}

}


import java.math.BigDecimal;


public class HoldingPositionWithPnL extends HoldingPositionWithAveragePrice {

private final BigDecimal valuation;

private final BigDecimal realizedPnL;

private final BigDecimal unrealizedPnL;


public HoldingPositionWithPnL(

String ticker,

String productName,

long quantity,

BigDecimal averageUnitPrice,

BigDecimal valuation,

BigDecimal realizedPnL,

BigDecimal unrealizedPnL

) {

super(ticker, productName, quantity, averageUnitPrice);

this.valuation = valuation;

this.realizedPnL = realizedPnL;

this.unrealizedPnL = unrealizedPnL;

}


public BigDecimal getValuation() {

return valuation;

}


public BigDecimal getRealizedPnL() {

return realizedPnL;

}


public BigDecimal getUnrealizedPnL() {

return unrealizedPnL;

}

}


import java.text.DecimalFormat;

import java.util.Comparator;

import java.util.List;


public class DisplayHoldingPosition {

private final List<HoldingPositionWithPnL> positions;


public DisplayHoldingPosition(List<HoldingPositionWithPnL> positions) {

this.positions = positions;

}


public void displayHoldingList() {

positions.sort(Comparator.comparing(HoldingPositionWithPnL::getTicker));

DecimalFormat decimalFormat = new DecimalFormat("##,###.###");


// 表ヘッダー

System.out.println("┌────────┬────────────────────────────────┬──────────────────┬───────────────┬──────────────┬──────────────┬──────────────┐");

System.out.printf("│ %-6s │ %-30s │ %-16s │ %-13s │ %-12s │ %-12s │ %-12s │%n",

"Ticker", "Product Name", "Quantity", "Avg Price", "Valuation", "Realized P&L", "Unrealized P&L");

System.out.println("├────────┼────────────────────────────────┼──────────────────┼───────────────┼──────────────┼──────────────┼──────────────┤");


// 表内容

for (HoldingPositionWithPnL position : positions) {

System.out.printf("│ %-6s │ %-30s │ %,16d │ %,13.2f │ %,12s │ %,12.2f │ %,12s │%n",

position.getTicker(),

position.getProductName(),

position.getQuantity(),

decimalFormat.format(position.getAverageUnitPrice()),

decimalFormat.format(position.getValuation() != null ? position.getValuation() : "N/A"),

decimalFormat.format(position.getRealizedPnL()),

decimalFormat.format(position.getUnrealizedPnL() != null ? position.getUnrealizedPnL() : "N/A"));

}


// 表フッター

System.out.println("└────────┴────────────────────────────────┴──────────────────┴───────────────┴──────────────┴──────────────┴──────────────┘");

}

}


import java.util.ArrayList;

import java.util.List;


public class CalculateQuantity {

public List<HoldingPosition> calculateQuantity(List<Trade> trades) {

List<HoldingPosition> positions = new ArrayList<>();


for (Trade trade : trades) {

long quantity = 0;

if (trade.getSide() == SideType.BUY) {

quantity = trade.getQuantity();

} else if (trade.getSide() == SideType.SELL) {

quantity = -trade.getQuantity();

}


String ticker = trade.getTicker();

HoldingPosition updatedPosition = null;


for (HoldingPosition position : positions) {

if (position.getTicker().equals(ticker)) {

long updatedQuantity = position.getQuantity() + quantity;

updatedPosition = new HoldingPosition(position.getTicker(), position.getProductName(), updatedQuantity);

positions.remove(position);

break;

}

}


if (updatedPosition == null) {

updatedPosition = new HoldingPosition(ticker, trade.getProductName(), quantity);

}


positions.add(updatedPosition);

}


return positions;

}

}


import java.math.BigDecimal;

import java.math.RoundingMode;

import java.util.ArrayList;

import java.util.List;


public class CalculateAvgUnitPrice {

private final List<HoldingPositionWithAveragePrice> positions;


public CalculateAvgUnitPrice() {

this.positions = new ArrayList<>();

}


public List<HoldingPositionWithAveragePrice> calculateAverageUnitPrice(List<Trade> trades) {

for (Trade trade : trades) {

String ticker = trade.getTicker();

BigDecimal tradedUnitPrice = trade.getTradedUnitPrice();

long tradeQuantity = trade.getQuantity();


HoldingPositionWithAveragePrice existingPosition = getPositionByTicker(ticker);


if (existingPosition == null) {

BigDecimal initialAveragePrice = BigDecimal.ZERO;

if (trade.getSide() == SideType.BUY) {

initialAveragePrice = tradedUnitPrice;

}

positions.add(new HoldingPositionWithAveragePrice(

ticker,

trade.getProductName(),

tradeQuantity,

initialAveragePrice

));

} else {

if (trade.getSide() == SideType.BUY) {

positions.remove(existingPosition);

positions.add(createUpdatedPositionForBuy(existingPosition, tradeQuantity, tradedUnitPrice));

} else {

positions.remove(existingPosition);

positions.add(createUpdatedPositionForSell(existingPosition, tradeQuantity));

}

}

}


return positions;

}


private HoldingPositionWithAveragePrice getPositionByTicker(String ticker) {

for (HoldingPositionWithAveragePrice position : positions) {

if (position.getTicker().equals(ticker)) {

return position;

}

}

return null;

}


private HoldingPositionWithAveragePrice createUpdatedPositionForBuy(

HoldingPositionWithAveragePrice position,

long tradeQuantity,

BigDecimal tradedUnitPrice

) {

long previousQuantity = position.getQuantity();

BigDecimal previousAveragePrice = position.getAverageUnitPrice();


BigDecimal totalCost = previousAveragePrice.multiply(BigDecimal.valueOf(previousQuantity))

.add(tradedUnitPrice.multiply(BigDecimal.valueOf(tradeQuantity)));

long newQuantity = previousQuantity + tradeQuantity;


BigDecimal newAveragePrice = totalCost.divide(BigDecimal.valueOf(newQuantity), 2, RoundingMode.HALF_UP);


return new HoldingPositionWithAveragePrice(

position.getTicker(),

position.getProductName(),

newQuantity,

newAveragePrice

);

}


private HoldingPositionWithAveragePrice createUpdatedPositionForSell(

HoldingPositionWithAveragePrice position,

long tradeQuantity

) {

long previousQuantity = position.getQuantity();

long newQuantity = previousQuantity - tradeQuantity;


return new HoldingPositionWithAveragePrice(

position.getTicker(),

position.getProductName(),

newQuantity,

position.getAverageUnitPrice()

);

}

}


import java.math.BigDecimal;

import java.math.RoundingMode;

import java.util.List;


public class CalculateRealizedPnL {


public BigDecimal calculate(List<Trade> trades, List<HoldingPositionWithAveragePrice> positions, String ticker) {

BigDecimal realizedPnL = BigDecimal.ZERO;


// HoldingPositionWithAveragePrice から該当ティッカーの平均取得単価を取得

BigDecimal averageUnitPrice = getAverageUnitPriceByTicker(positions, ticker);


for (Trade trade : trades) {

if (trade.getTicker().equals(ticker) && trade.getSide() == SideType.SELL) {

BigDecimal tradePnL = BigDecimal.valueOf(trade.getQuantity())

.multiply(trade.getTradedUnitPrice().subtract(averageUnitPrice));

realizedPnL = realizedPnL.add(tradePnL);

}

}


return realizedPnL.setScale(2, RoundingMode.HALF_UP);

}


private BigDecimal getAverageUnitPriceByTicker(List<HoldingPositionWithAveragePrice> positions, String ticker) {

for (HoldingPositionWithAveragePrice position : positions) {

if (position.getTicker().equals(ticker)) {

return position.getAverageUnitPrice();

}

}

return null; // 該当ティッカーがない場合

}

}


import java.math.BigDecimal;

import java.math.RoundingMode;


public class CalculateUnrealizedPnL {


public BigDecimal calculate(long quantity, BigDecimal avgUnitPrice, BigDecimal valuation) {

if (valuation == null) {

return null; // 時価が取得できない場合

}

BigDecimal cost = BigDecimal.valueOf(quantity).multiply(avgUnitPrice);

return valuation.subtract(cost).setScale(2, RoundingMode.HALF_UP);

}

}


import java.math.BigDecimal;

import java.math.RoundingMode;


public class CalculateValuation {


public BigDecimal calculate(long quantity, BigDecimal marketPrice) {

if (marketPrice == null) {

return null; // 時価が取得できない場合

}

return BigDecimal.valueOf(quantity).multiply(marketPrice).setScale(2, RoundingMode.HALF_UP);

}

}


import java.math.BigDecimal;

import java.util.ArrayList;

import java.util.List;


public class OrganizePnL {

private final List<HoldingPositionWithAveragePrice> positions;

private final List<MarketValue> marketValues;


public OrganizePnL(List<HoldingPositionWithAveragePrice> positions, List<MarketValue> marketValues) {

this.positions = positions;

this.marketValues = marketValues;

}


public List<HoldingPositionWithPnL> organize(List<Trade> trades) {

List<HoldingPositionWithPnL> result = new ArrayList<>();


CalculateRealizedPnL calculateRealizedPnL = new CalculateRealizedPnL();

CalculateValuation calculateValuation = new CalculateValuation();

CalculateUnrealizedPnL calculateUnrealizedPnL = new CalculateUnrealizedPnL();


for (HoldingPositionWithAveragePrice position : positions) {

String ticker = position.getTicker();

long holdingQuantity = position.getQuantity();

BigDecimal avgUnitPrice = position.getAverageUnitPrice();


// 時価を取得

BigDecimal marketPrice = getMarketPriceByTicker(ticker);


// Valuation

BigDecimal valuation = calculateValuation.calculate(holdingQuantity, marketPrice);


// Unrealized P&L

BigDecimal unrealizedPnL = calculateUnrealizedPnL.calculate(holdingQuantity, avgUnitPrice, valuation);


// Realized P&L

BigDecimal realizedPnL = calculateRealizedPnL.calculate(trades, positions, ticker);


result.add(new HoldingPositionWithPnL(

ticker,

position.getProductName(),

holdingQuantity,

avgUnitPrice,

valuation,

realizedPnL,

unrealizedPnL

));

}


return result;

}


private BigDecimal getMarketPriceByTicker(String ticker) {

for (MarketValue marketValue : marketValues) {

if (marketValue.getTicker().equals(ticker)) {

return marketValue.getMarketPrice();

}

}

return null; // 時価が取得できない場合

}

}


評価をするにはログインしてください。
この作品をシェア
Twitter LINEで送る
ブックマークに追加
ブックマーク機能を使うにはログインしてください。
― 新着の感想 ―
このエピソードに感想はまだ書かれていません。
感想一覧
+注意+

特に記載なき場合、掲載されている作品はすべてフィクションであり実在の人物・団体等とは一切関係ありません。
特に記載なき場合、掲載されている作品の著作権は作者にあります(一部作品除く)。
作者以外の方による作品の引用を超える無断転載は禁止しており、行った場合、著作権法の違反となります。

この作品はリンクフリーです。ご自由にリンク(紹介)してください。
この作品はスマートフォン対応です。スマートフォンかパソコンかを自動で判別し、適切なページを表示します。

↑ページトップへ