Skip to content

Instantly share code, notes, and snippets.

@odrobnik
Created February 8, 2023 21:33
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save odrobnik/21fdf118f1a458f2a37289c9ddb77de8 to your computer and use it in GitHub Desktop.
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
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