美股記帳 App / Part 3 均價獲利計算 & Charts 製作圖表分析
Published in
9 min readMar 21, 2022
功能:
- Average Price, Average Dollar Cost, Earning, Money Balance
- 以個股獲利所製作的 Pie Chart
報表內容
- totalQuantity : 股票總共的張數
- totalDollarCost : 每次交易的金錢總和 (money balance)
- AverageDollarCost :totalDollarCost / totalQuantity * -1
- AveragePrice :現有股票的均價
- preAveragePrice :前一次的均價,方便計算 AveragePriceChange 和 AveragePriceChangePercentage
- Earning: 每一次賣掉股票時,依 AveragePrice 所算的獲利
struct stockStatistics : Codable{
let stockSymbol : String
var totalQuantity : Double
var totalDollarCost : Double var AverageDollarCost : Double{
if totalQuantity == 0{
return 0
}else{
return totalDollarCost / totalQuantity * -1.0
}
}
var AveragePrice: Double
var prevAveragePrice : Double
var AveragePriceChange : Double{
return AveragePrice - prevAveragePrice
}
var AveragePriceChangePercentage : Double{
if prevAveragePrice == 0 {
return 0
}
return AveragePriceChange / prevAveragePrice
}
var earning : Double
var earningChange : Double
}
均價算法
- 按時間由早到晚重新將 transactionRecords 排序
- 透過 for loop 跑過每一個 transaction
- 第一筆交易時,AveragePrice 為購買股票的價格
- 買進股票時,AveragePrice 為 ( 買進之前的 AveragePrice 乘以 買進之前的總張數 加上 這次買進的股票價格 乘以 這次買進的張數)除以 買進的總張數
- 賣掉股票時,AveragePrice 不變,Earning 為 (賣掉股價 減 AveragePrice ) 乘以 賣掉股票的張數
- 經過測試,在股票全部賣掉後,用 AveragePrice 計算的 Earning 會和 Money Balance 一樣,代表這個算法是可行的喔!!!
Pie Chart
1.下載第三方套件 Charts 並安裝
2. 設定 Entry
- Entry : data value
- 使用 map 取出 symbolStock 當 pie chart 的label,並通過 function 得到該股票的 earning 當 pie chart 的 value
func getEarning(stockSymbol : String) -> Double{
if let index = stockStatisticsList.firstIndex(where: {$0.stockSymbol == stockSymbol}){
return stockStatisticsList[index].earning
}
return 0
}let pieChartDataEntries = symbolList.map({(symbol) -> PieChartDataEntry in
return PieChartDataEntry(value: getEarning(stockSymbol: symbol), label:symbol)
})
3. 設定 dataSet
- dataSet : 設定 entry 要展現的設定
- selectionShift : 選中的 pie 會往外移多少
- sliceSpace:每個 pie 之間的縫隙
- color : pie 的顏色,因為股票的數量每次可能都不一樣,所以選擇 chartColorTemplates 裡配好的一系列顏色
let pieChartDataSet = PieChartDataSet(entries: pieChartDataEntries, label: "")pieChartDataSet.selectionShift = 10
pieChartDataSet.sliceSpace = 2
pieChartDataSet.colors = ChartColorTemplates.pastel() + ChartColorTemplates.material()
4. 設定 data
- data : 設定 entry 裡 value 呈現的方式
- setValueFormatter 裡的 input 要遵從 NSObject, protocol: ValueFormatter 所以要額外寫一個 class
let pieChartData = PieChartData(dataSet: pieChartDataSet)
pieChartData.setValueFormatter(percentageValueFormatter())
pieChartData.setValueFont(.systemFont(ofSize: 12, weight: .regular))
pieChartData.setValueTextColor(.white)
class percentageValueFormatter : NSObject,ValueFormatter{
func stringForValue(_ value: Double, entry: ChartDataEntry, dataSetIndex: Int, viewPortHandler: ViewPortHandler?) -> String {
return String(format: "%.1f%%", value)
}
}
5. 設定 chartView
- usePerventValuesEnabled : 讓資料以百分比呈現
- animate : 顯示圖的動畫
- sliceTextDrawingThreshold : 如果 pie小於設定的 degree ,pie 裡就不會有文字 (怕 pie 太小,字全都擠在一起)
pieChartView.data = pieChartDatapieChartView.usePercentValuesEnabled = truepieChartView.animate(xAxisDuration: 1.0, yAxisDuration: 1.0)pieChartView.sliceTextDrawingThreshold = 20
6. 設定 legend
let legend = pieChartView.legend
legend.horizontalAlignment = .center
legend.verticalAlignment = .bottom
legend.orientation = .horizontal
legend.textColor = .white
legend.font = UIFont.systemFont(ofSize: 12)
legend.form = .circle
legend.formToTextSpace = 4
legend.formSize = 10
7. 設定 pie chart 中間的字
let totalEarning = stockStatisticsList.reduce(0.0, {$0 + $1.earning})pieChartView.centerText = "Total Earning :\n \(totalEarning.getCurrencyFormat())"