Created
February 8, 2023 21:33
-
-
Save odrobnik/21fdf118f1a458f2a37289c9ddb77de8 to your computer and use it in GitHub Desktop.
Command Line utility to convert Yahoo Finance CSV export into markdown table for ChatGPT
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import SwiftCSV | |
import Foundation | |
extension Double { | |
/// Rounds the double to decimal places value | |
func rounded(toPlaces places:Int) -> Double { | |
let divisor = pow(10.0, Double(places)) | |
return (self * divisor).rounded() / divisor | |
} | |
} | |
guard CommandLine.arguments.count >= 2 else { | |
print("Usage: yMunch path/to/input_file.csv") | |
exit(1) | |
} | |
let fileManager = FileManager.default | |
let currentDirectory = fileManager.currentDirectoryPath | |
let inputFile = CommandLine.arguments[1] | |
let fileURL = URL(fileURLWithPath: inputFile.hasPrefix("/") ? inputFile : "\(currentDirectory)/\(inputFile)") | |
var transactionsBySymbol = [String: (quantity: Double, purchasePrice: Double, currentPrice: Double)]() | |
do { | |
let csv = try CSV<Named>(url: fileURL) // I needed to add the <Named> and change the param to url: | |
let rows = csv.rows | |
for row in rows { | |
let symbol = row["Symbol"]! | |
let quantity = Double(row["Quantity"]!)! | |
let purchasePrice = Double(row["Purchase Price"]!)! | |
let currentPrice = Double(row["Current Price"]!)! | |
if transactionsBySymbol[symbol] == nil { | |
transactionsBySymbol[symbol] = (quantity: 0, purchasePrice: 0, currentPrice: 0) | |
} | |
var transaction = transactionsBySymbol[symbol]! | |
transaction.quantity += quantity | |
transaction.purchasePrice = (transaction.purchasePrice * (transaction.quantity - quantity) + quantity * purchasePrice) / transaction.quantity | |
transaction.currentPrice = currentPrice | |
transactionsBySymbol[symbol] = transaction | |
} | |
} catch { | |
print("Error reading input file: \(error)") | |
} | |
let transactions = transactionsBySymbol.map { (symbol, transaction) in | |
let averagePurchasePrice = transaction.purchasePrice | |
let totalQuantity = transaction.quantity | |
let currentPrice = transaction.currentPrice | |
let totalMarketValue = totalQuantity * currentPrice | |
let profitLoss = totalQuantity * (currentPrice - averagePurchasePrice) | |
return (symbol: symbol, totalQuantity: totalQuantity, averagePurchasePrice: averagePurchasePrice, currentPrice: currentPrice, totalMarketValue: totalMarketValue, profitLoss: profitLoss) | |
} | |
let sortedTransactions = transactions.sorted { $0.profitLoss < $1.profitLoss } | |
print("| Symbol | Quantity | Average Price | Current Price | Current Market Value | Unrealized Performance |") | |
print("| --- | --- | --- | --- | --- | --- |") | |
for transaction in sortedTransactions { | |
let symbol = transaction.symbol | |
let averagePurchasePrice = transaction.averagePurchasePrice.rounded(toPlaces: 2) | |
let totalQuantity = Int(transaction.totalQuantity) | |
let currentPrice = transaction.currentPrice.rounded(toPlaces: 2) | |
let totalMarketValue = transaction.totalMarketValue.rounded(toPlaces: 2) | |
let profitLoss = transaction.profitLoss.rounded(toPlaces: 2) | |
print("| \(symbol) | \(totalQuantity) | \(averagePurchasePrice) | \(currentPrice) | \(totalMarketValue) | \(profitLoss) |") | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment