2017-03-22 20:29:08 -04:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"flag"
|
|
|
|
"fmt"
|
|
|
|
"github.com/aclindsa/ofxgo"
|
|
|
|
"os"
|
|
|
|
)
|
|
|
|
|
2017-04-16 20:50:06 -04:00
|
|
|
var invTransactionsCommand = command{
|
2017-03-22 20:29:08 -04:00
|
|
|
Name: "transactions-inv",
|
|
|
|
Description: "Print investment transactions",
|
|
|
|
Flags: flag.NewFlagSet("transactions-inv", flag.ExitOnError),
|
|
|
|
CheckFlags: checkServerFlags,
|
|
|
|
Do: invTransactions,
|
|
|
|
}
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
defineServerFlags(invTransactionsCommand.Flags)
|
2017-04-12 21:40:42 -04:00
|
|
|
invTransactionsCommand.Flags.StringVar(&acctID, "acctid", "", "AcctID (from `get-accounts` subcommand)")
|
|
|
|
invTransactionsCommand.Flags.StringVar(&brokerID, "brokerid", "", "BrokerID (from `get-accounts` subcommand)")
|
2017-03-22 20:29:08 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func invTransactions() {
|
2017-04-16 20:50:06 -04:00
|
|
|
client, query := newRequest()
|
2017-03-22 20:29:08 -04:00
|
|
|
|
|
|
|
uid, err := ofxgo.RandomUID()
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println("Error creating uid for transaction:", err)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
statementRequest := ofxgo.InvStatementRequest{
|
|
|
|
TrnUID: *uid,
|
|
|
|
InvAcctFrom: ofxgo.InvAcct{
|
2017-04-12 21:40:42 -04:00
|
|
|
BrokerID: ofxgo.String(brokerID),
|
|
|
|
AcctID: ofxgo.String(acctID),
|
2017-03-22 20:29:08 -04:00
|
|
|
},
|
|
|
|
Include: true,
|
2017-03-28 19:42:16 -04:00
|
|
|
IncludeOO: true,
|
|
|
|
IncludePos: true,
|
2017-03-22 20:29:08 -04:00
|
|
|
IncludeBalance: true,
|
2017-03-28 19:42:16 -04:00
|
|
|
Include401K: true,
|
|
|
|
Include401KBal: true,
|
2017-03-22 20:29:08 -04:00
|
|
|
}
|
2017-03-31 11:54:43 -04:00
|
|
|
query.InvStmt = append(query.InvStmt, &statementRequest)
|
2017-03-22 20:29:08 -04:00
|
|
|
|
2023-02-05 19:17:05 -05:00
|
|
|
if dryrun {
|
|
|
|
printRequest(client, query)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-03-22 20:29:08 -04:00
|
|
|
response, err := client.Request(query)
|
|
|
|
if err != nil {
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
if response.Signon.Status.Code != 0 {
|
2017-03-25 06:14:52 -04:00
|
|
|
meaning, _ := response.Signon.Status.CodeMeaning()
|
|
|
|
fmt.Printf("Nonzero signon status (%d: %s) with message: %s\n", response.Signon.Status.Code, meaning, response.Signon.Status.Message)
|
2017-03-22 20:29:08 -04:00
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
2017-03-31 11:54:43 -04:00
|
|
|
if len(response.InvStmt) < 1 {
|
2017-03-22 20:29:08 -04:00
|
|
|
fmt.Println("No investment messages received")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-03-31 11:54:43 -04:00
|
|
|
if stmt, ok := response.InvStmt[0].(*ofxgo.InvStatementResponse); ok {
|
2017-04-03 21:15:08 -04:00
|
|
|
availCash := stmt.InvBal.AvailCash
|
2017-03-22 20:29:08 -04:00
|
|
|
if availCash.IsInt() && availCash.Num().Int64() != 0 {
|
|
|
|
fmt.Printf("Balance: %s %s (as of %s)\n", stmt.InvBal.AvailCash, stmt.CurDef, stmt.DtAsOf)
|
|
|
|
}
|
|
|
|
for _, banktrans := range stmt.InvTranList.BankTransactions {
|
|
|
|
fmt.Printf("\nBank Transactions for %s subaccount:\n", banktrans.SubAcctFund)
|
|
|
|
for _, tran := range banktrans.Transactions {
|
|
|
|
printTransaction(stmt.CurDef, &tran)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fmt.Printf("\nInvestment Transactions:\n")
|
|
|
|
for _, t := range stmt.InvTranList.InvTransactions {
|
|
|
|
fmt.Printf("%-14s", t.TransactionType())
|
|
|
|
switch tran := t.(type) {
|
|
|
|
case ofxgo.BuyDebt:
|
|
|
|
printInvBuy(stmt.CurDef, &tran.InvBuy)
|
|
|
|
case ofxgo.BuyMF:
|
|
|
|
printInvBuy(stmt.CurDef, &tran.InvBuy)
|
|
|
|
case ofxgo.BuyOpt:
|
|
|
|
printInvBuy(stmt.CurDef, &tran.InvBuy)
|
|
|
|
case ofxgo.BuyOther:
|
|
|
|
printInvBuy(stmt.CurDef, &tran.InvBuy)
|
|
|
|
case ofxgo.BuyStock:
|
|
|
|
printInvBuy(stmt.CurDef, &tran.InvBuy)
|
|
|
|
case ofxgo.ClosureOpt:
|
|
|
|
printInvTran(&tran.InvTran)
|
2017-03-28 19:47:17 -04:00
|
|
|
fmt.Printf("%s %s contracts (%d shares each)\n", tran.OptAction, tran.Units, tran.ShPerCtrct)
|
2017-03-22 20:29:08 -04:00
|
|
|
case ofxgo.Income:
|
|
|
|
printInvTran(&tran.InvTran)
|
|
|
|
currency := stmt.CurDef
|
2017-04-19 21:23:37 -04:00
|
|
|
if ok, _ := tran.Currency.Valid(); ok {
|
2017-03-22 20:29:08 -04:00
|
|
|
currency = tran.Currency.CurSym
|
|
|
|
}
|
2017-04-12 21:40:42 -04:00
|
|
|
fmt.Printf(" %s %s %s (%s %s)\n", tran.IncomeType, tran.Total, currency, tran.SecID.UniqueIDType, tran.SecID.UniqueID)
|
2017-03-22 20:29:08 -04:00
|
|
|
// TODO print ticker instead of CUSIP
|
|
|
|
case ofxgo.InvExpense:
|
|
|
|
printInvTran(&tran.InvTran)
|
|
|
|
currency := stmt.CurDef
|
2017-04-19 21:23:37 -04:00
|
|
|
if ok, _ := tran.Currency.Valid(); ok {
|
2017-03-22 20:29:08 -04:00
|
|
|
currency = tran.Currency.CurSym
|
|
|
|
}
|
2017-04-12 21:40:42 -04:00
|
|
|
fmt.Printf(" %s %s (%s %s)\n", tran.Total, currency, tran.SecID.UniqueIDType, tran.SecID.UniqueID)
|
2017-03-22 20:29:08 -04:00
|
|
|
// TODO print ticker instead of CUSIP
|
|
|
|
case ofxgo.JrnlFund:
|
|
|
|
printInvTran(&tran.InvTran)
|
|
|
|
fmt.Printf(" %s %s (%s -> %s)\n", tran.Total, stmt.CurDef, tran.SubAcctFrom, tran.SubAcctTo)
|
|
|
|
case ofxgo.JrnlSec:
|
|
|
|
printInvTran(&tran.InvTran)
|
2017-04-12 21:40:42 -04:00
|
|
|
fmt.Printf(" %s %s %s (%s -> %s)\n", tran.Units, tran.SecID.UniqueIDType, tran.SecID.UniqueID, tran.SubAcctFrom, tran.SubAcctTo)
|
2017-03-22 20:29:08 -04:00
|
|
|
// TODO print ticker instead of CUSIP
|
|
|
|
case ofxgo.MarginInterest:
|
|
|
|
printInvTran(&tran.InvTran)
|
|
|
|
currency := stmt.CurDef
|
2017-04-19 21:23:37 -04:00
|
|
|
if ok, _ := tran.Currency.Valid(); ok {
|
2017-03-22 20:29:08 -04:00
|
|
|
currency = tran.Currency.CurSym
|
|
|
|
}
|
|
|
|
fmt.Printf(" %s %s\n", tran.Total, currency)
|
|
|
|
case ofxgo.Reinvest:
|
|
|
|
printInvTran(&tran.InvTran)
|
|
|
|
currency := stmt.CurDef
|
2017-04-19 21:23:37 -04:00
|
|
|
if ok, _ := tran.Currency.Valid(); ok {
|
2017-03-22 20:29:08 -04:00
|
|
|
currency = tran.Currency.CurSym
|
|
|
|
}
|
2017-04-12 21:40:42 -04:00
|
|
|
fmt.Printf(" %s (%s %s)@%s %s (Total: %s)\n", tran.Units, tran.SecID.UniqueIDType, tran.SecID.UniqueID, tran.UnitPrice, currency, tran.Total)
|
2017-03-22 20:29:08 -04:00
|
|
|
// TODO print ticker instead of CUSIP
|
|
|
|
case ofxgo.RetOfCap:
|
|
|
|
printInvTran(&tran.InvTran)
|
|
|
|
currency := stmt.CurDef
|
2017-04-19 21:23:37 -04:00
|
|
|
if ok, _ := tran.Currency.Valid(); ok {
|
2017-03-22 20:29:08 -04:00
|
|
|
currency = tran.Currency.CurSym
|
|
|
|
}
|
2017-04-12 21:40:42 -04:00
|
|
|
fmt.Printf(" %s %s (%s %s)\n", tran.Total, currency, tran.SecID.UniqueIDType, tran.SecID.UniqueID)
|
2017-03-22 20:29:08 -04:00
|
|
|
// TODO print ticker instead of CUSIP
|
|
|
|
case ofxgo.SellDebt:
|
|
|
|
printInvSell(stmt.CurDef, &tran.InvSell)
|
|
|
|
case ofxgo.SellMF:
|
|
|
|
printInvSell(stmt.CurDef, &tran.InvSell)
|
|
|
|
case ofxgo.SellOpt:
|
|
|
|
printInvSell(stmt.CurDef, &tran.InvSell)
|
|
|
|
case ofxgo.SellOther:
|
|
|
|
printInvSell(stmt.CurDef, &tran.InvSell)
|
|
|
|
case ofxgo.SellStock:
|
|
|
|
printInvSell(stmt.CurDef, &tran.InvSell)
|
|
|
|
case ofxgo.Split:
|
|
|
|
printInvTran(&tran.InvTran)
|
|
|
|
currency := stmt.CurDef
|
2017-04-19 21:23:37 -04:00
|
|
|
if ok, _ := tran.Currency.Valid(); ok {
|
2017-03-22 20:29:08 -04:00
|
|
|
currency = tran.Currency.CurSym
|
|
|
|
}
|
2017-04-12 21:40:42 -04:00
|
|
|
fmt.Printf(" %d/%d %s -> %s shares of %s %s (%s %s for fractional shares)\n", tran.Numerator, tran.Denominator, tran.OldUnits, tran.NewUnits, tran.SecID.UniqueIDType, tran.SecID.UniqueID, tran.FracCash, currency)
|
2017-03-22 20:29:08 -04:00
|
|
|
// TODO print ticker instead of CUSIP
|
|
|
|
case ofxgo.Transfer:
|
|
|
|
printInvTran(&tran.InvTran)
|
2017-04-12 21:40:42 -04:00
|
|
|
fmt.Printf(" %s (%s %s) %s\n", tran.Units, tran.SecID.UniqueIDType, tran.SecID.UniqueID, tran.TferAction)
|
2017-03-22 20:29:08 -04:00
|
|
|
// TODO print ticker instead of CUSIP
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func printInvTran(it *ofxgo.InvTran) {
|
|
|
|
fmt.Printf("%s", it.DtTrade)
|
|
|
|
}
|
|
|
|
|
2017-04-17 20:20:22 -04:00
|
|
|
func printInvBuy(defCurrency ofxgo.CurrSymbol, ib *ofxgo.InvBuy) {
|
2017-03-22 20:29:08 -04:00
|
|
|
printInvTran(&ib.InvTran)
|
|
|
|
currency := defCurrency
|
2017-04-19 21:23:37 -04:00
|
|
|
if ok, _ := ib.Currency.Valid(); ok {
|
2017-03-22 20:29:08 -04:00
|
|
|
currency = ib.Currency.CurSym
|
|
|
|
}
|
|
|
|
|
2017-04-12 21:40:42 -04:00
|
|
|
fmt.Printf("%s (%s %s)@%s %s (Total: %s)\n", ib.Units, ib.SecID.UniqueIDType, ib.SecID.UniqueID, ib.UnitPrice, currency, ib.Total)
|
2017-03-22 20:29:08 -04:00
|
|
|
// TODO print ticker instead of CUSIP
|
|
|
|
}
|
|
|
|
|
2017-04-17 20:20:22 -04:00
|
|
|
func printInvSell(defCurrency ofxgo.CurrSymbol, is *ofxgo.InvSell) {
|
2017-03-22 20:29:08 -04:00
|
|
|
printInvTran(&is.InvTran)
|
|
|
|
currency := defCurrency
|
2017-04-19 21:23:37 -04:00
|
|
|
if ok, _ := is.Currency.Valid(); ok {
|
2017-03-22 20:29:08 -04:00
|
|
|
currency = is.Currency.CurSym
|
|
|
|
}
|
|
|
|
|
2017-04-17 20:20:22 -04:00
|
|
|
fmt.Printf(" %s (%s %s)@%s %s (Total: %s)\n", is.Units, is.SecID.UniqueIDType, is.SecID.UniqueID, is.UnitPrice, currency.String(), is.Total)
|
2017-03-22 20:29:08 -04:00
|
|
|
// TODO print ticker instead of CUSIP
|
|
|
|
}
|