package ofxgo_test
import (
	"github.com/aclindsa/xml"
	"github.com/aclindsa/ofxgo"
	"reflect"
	"strings"
	"testing"
	"time"
)
func TestMarshalInvStatementRequest(t *testing.T) {
	var expectedString string = `
	
		
			20160224131905.000[-5:EST]
			1998124
			Sup3eSekrit
			ENG
			
				First Bank
				01
			
			MYAPP
			1234
		
	
	
		
			382827d6-e2d0-4396-bf3b-665979285420
			
				
					fi.example.com
					82736664
				
				
					20160101000000.000[-5:EST]
					Y
				
				Y
				
					Y
				
				Y
			
		
	
`
	var client = ofxgo.Client{
		AppID:       "MYAPP",
		AppVer:      "1234",
		SpecVersion: ofxgo.OfxVersion203,
	}
	var request ofxgo.Request
	request.Signon.UserID = "1998124"
	request.Signon.UserPass = "Sup3eSekrit"
	request.Signon.Org = "First Bank"
	request.Signon.Fid = "01"
	EST := time.FixedZone("EST", -5*60*60)
	statementRequest := ofxgo.InvStatementRequest{
		TrnUID: "382827d6-e2d0-4396-bf3b-665979285420",
		InvAcctFrom: ofxgo.InvAcct{
			BrokerID: "fi.example.com",
			AcctID:   "82736664",
		},
		DtStart:        ofxgo.NewDate(2016, 1, 1, 0, 0, 0, 0, EST),
		Include:        true,
		IncludeOO:      true,
		IncludePos:     true,
		IncludeBalance: true,
	}
	request.InvStmt = append(request.InvStmt, &statementRequest)
	request.SetClientFields(&client)
	// Overwrite the DtClient value set by SetClientFields to time.Now()
	request.Signon.DtClient = *ofxgo.NewDate(2016, 2, 24, 13, 19, 5, 0, EST)
	marshalCheckRequest(t, &request, expectedString)
}
func TestUnmarshalInvStatementResponse(t *testing.T) {
	responseReader := strings.NewReader(`
	
		
			
				0
				INFO
			
			20170401201244
			ENG
			
				INVSTRUS
				9999
			
		
	
	
		
			1a0117ad-692b-4c6a-a21b-020d37d34d49
			
				0
				INFO
			
			
				20170331000000
				USD
				
					invstrus.com
					91827364
				
				
					20170101000000
					20170331000000
					
						
							
								729483191
								20170203
								20170207
							
							
								78462F103
								CUSIP
							
							100
							229.00
							9.00
							-22909.00
							CASH
							CASH
						
						BUY
					
					
						
							CREDIT
							20170120
							20170118
							20170123
							22000.00
							993838
							DEPOSIT
							CHECK 19980
						
						CASH
					
				
				
					
						
							
								78462F103
								CUSIP
							
							CASH
							LONG
							200
							235.74
							47148.00
							20170331160000
							Price as of previous close
						
					
					
						
							
								129887339
								CUSIP
							
							CASH
							LONG
							1
							3
							300
							20170331160000
						
					
				
				
					16.73
					-819.20
					0
					
						
							Sweep Int Rate
							Current interest rate for sweep account balances
							PERCENT
							0.25
							20170401
						
					
				
				
					
						
							76464632
							
								922908645
								CUSIP
							
							20170310124445
							10
							CASH
							GOODTILCANCEL
							NONE
							168.50
						
						BUY
						SHARES
					
					
						
							999387423
							
								899422348
								CUSIP
							
							20170324031900
							25
							CASH
							GOODTILCANCEL
							ALLORNONE
							19.75
						
						BUY
					
				
			
		
	
	
		
			
				
					
						78462F103
						CUSIP
					
					S&P 500 ETF
					SPY
					99184
				
				1.92
				OTHER
			
			
				
					
						129887339
						CUSIP
					
					John's Fertilizer Puts
					FERTP
					882919
				
				PUT
				79.00
				20170901
				100
				
					983322180
					CUSIP
				
				LARGESTOCK
			
			
				
					
						899422348
						CUSIP
					
					Whatchamacallit, Inc.
					WHAT
					883897
				
				17
				SMALLSTOCK
			
			
				
					
						922908645
						CUSIP
					
					Mid-Cap Index Fund Admiral Shares
					VIMAX
				
			
			
				
					
						99182828
						CUSIP
					
					Someone's Class B Debt
				
				100.29
				COUPON
				20170901
				QUARTERLY
			
			
				
					
						88181818
						CUSIP
					
					Foo Bar
				
				Don't know what this is
			
		
	
`)
	var expected ofxgo.Response
	expected.Version = ofxgo.OfxVersion203
	expected.Signon.Status.Code = 0
	expected.Signon.Status.Severity = "INFO"
	expected.Signon.DtServer = *ofxgo.NewDateGMT(2017, 4, 1, 20, 12, 44, 0)
	expected.Signon.Language = "ENG"
	expected.Signon.Org = "INVSTRUS"
	expected.Signon.Fid = "9999"
	var units1, unitprice1, commission1, total1, amount2 ofxgo.Amount
	units1.SetFrac64(100, 1)
	unitprice1.SetFrac64(229, 1)
	commission1.SetFrac64(9, 1)
	total1.SetFrac64(-22909, 1)
	amount2.SetFrac64(22000, 1)
	invtranlist := ofxgo.InvTranList{
		DtStart: *ofxgo.NewDateGMT(2017, 1, 1, 0, 0, 0, 0),
		DtEnd:   *ofxgo.NewDateGMT(2017, 3, 31, 0, 0, 0, 0),
		InvTransactions: []ofxgo.InvTransaction{
			ofxgo.BuyStock{
				InvBuy: ofxgo.InvBuy{
					InvTran: ofxgo.InvTran{
						FiTID:    "729483191",
						DtTrade:  *ofxgo.NewDateGMT(2017, 2, 3, 0, 0, 0, 0),
						DtSettle: ofxgo.NewDateGMT(2017, 2, 7, 0, 0, 0, 0),
					},
					SecID: ofxgo.SecurityID{
						UniqueID:     "78462F103",
						UniqueIDType: "CUSIP",
					},
					Units:       units1,
					UnitPrice:   unitprice1,
					Commission:  commission1,
					Total:       total1,
					SubAcctSec:  ofxgo.SubAcctTypeCash,
					SubAcctFund: ofxgo.SubAcctTypeCash,
				},
				BuyType: ofxgo.BuyTypeBuy,
			},
		},
		BankTransactions: []ofxgo.InvBankTransaction{
			{
				Transactions: []ofxgo.Transaction{
					{
						TrnType:  ofxgo.TrnTypeCredit,
						DtPosted: *ofxgo.NewDateGMT(2017, 1, 20, 0, 0, 0, 0),
						DtUser:   ofxgo.NewDateGMT(2017, 1, 18, 0, 0, 0, 0),
						DtAvail:  ofxgo.NewDateGMT(2017, 1, 23, 0, 0, 0, 0),
						TrnAmt: amount2,
						FiTID:  "993838",
						Name:   "DEPOSIT",
						Memo:   "CHECK 19980",
					},
				},
				SubAcctFund: ofxgo.SubAcctTypeCash,
			},
		},
	}
	var availcash, marginbalance, shortbalance, balvalue ofxgo.Amount
	availcash.SetFrac64(1673, 100)
	marginbalance.SetFrac64(-8192, 10)
	shortbalance.SetFrac64(0, 1)
	balvalue.SetFrac64(25, 100)
	invbalance := ofxgo.InvBalance{
		AvailCash:     availcash,
		MarginBalance: marginbalance,
		ShortBalance:  shortbalance,
		BalList: []ofxgo.Balance{
			{
				Name:    "Sweep Int Rate",
				Desc:    "Current interest rate for sweep account balances",
				BalType: ofxgo.BalTypePercent,
				Value:   balvalue,
				DtAsOf:  ofxgo.NewDateGMT(2017, 4, 1, 0, 0, 0, 0),
			},
		},
	}
	var balamt, availbalamt, posunits1, posunitprice1, posmktval1, posunits2, posunitprice2, posmktval2, oounits1, oolimitprice1, oounits2, oolimitprice2 ofxgo.Amount
	balamt.SetFrac64(20029, 100)
	availbalamt.SetFrac64(20029, 100)
	posunits1.SetFrac64(200, 1)
	posunitprice1.SetFrac64(23574, 100)
	posmktval1.SetFrac64(47148, 1)
	posunits2.SetFrac64(1, 1)
	posunitprice2.SetFrac64(3, 1)
	posmktval2.SetFrac64(300, 1)
	oounits1.SetFrac64(10, 1)
	oolimitprice1.SetFrac64(16850, 100)
	oounits2.SetFrac64(25, 1)
	oolimitprice2.SetFrac64(1975, 100)
	usd, err := ofxgo.NewCurrSymbol("USD")
	if err != nil {
		t.Fatalf("Unexpected error creating CurrSymbol for USD\n")
	}
	statementResponse := ofxgo.InvStatementResponse{
		TrnUID: "1a0117ad-692b-4c6a-a21b-020d37d34d49",
		Status: ofxgo.Status{
			Code:     0,
			Severity: "INFO",
		},
		DtAsOf: *ofxgo.NewDateGMT(2017, 3, 31, 0, 0, 0, 0),
		CurDef: *usd,
		InvAcctFrom: ofxgo.InvAcct{
			BrokerID: "invstrus.com",
			AcctID:   "91827364",
		},
		InvTranList: &invtranlist,
		InvPosList: ofxgo.PositionList{
			ofxgo.StockPosition{
				InvPos: ofxgo.InvPosition{
					SecID: ofxgo.SecurityID{
						UniqueID:     "78462F103",
						UniqueIDType: "CUSIP",
					},
					HeldInAcct:  ofxgo.SubAcctTypeCash,
					PosType:     ofxgo.PosTypeLong,
					Units:       posunits1,
					UnitPrice:   posunitprice1,
					MktVal:      posmktval1,
					DtPriceAsOf: *ofxgo.NewDateGMT(2017, 3, 31, 16, 0, 0, 0),
					Memo:        "Price as of previous close",
				},
			},
			ofxgo.OptPosition{
				InvPos: ofxgo.InvPosition{
					SecID: ofxgo.SecurityID{
						UniqueID:     "129887339",
						UniqueIDType: "CUSIP",
					},
					HeldInAcct:  ofxgo.SubAcctTypeCash,
					PosType:     ofxgo.PosTypeLong,
					Units:       posunits2,
					UnitPrice:   posunitprice2,
					MktVal:      posmktval2,
					DtPriceAsOf: *ofxgo.NewDateGMT(2017, 3, 31, 16, 0, 0, 0),
				},
			},
		},
		InvBal: &invbalance,
		InvOOList: ofxgo.OOList{
			ofxgo.OOBuyMF{
				OO: ofxgo.OO{
					FiTID: "76464632",
					SecID: ofxgo.SecurityID{
						UniqueID:     "922908645",
						UniqueIDType: "CUSIP",
					},
					DtPlaced:    *ofxgo.NewDateGMT(2017, 3, 10, 12, 44, 45, 0),
					Units:       oounits1,
					SubAcct:     ofxgo.SubAcctTypeCash,
					Duration:    ofxgo.DurationGoodTilCancel,
					Restriction: ofxgo.RestrictionNone,
					LimitPrice:  oolimitprice1,
				},
				BuyType:  ofxgo.BuyTypeBuy,
				UnitType: ofxgo.UnitTypeShares,
			},
			ofxgo.OOBuyStock{
				OO: ofxgo.OO{
					FiTID: "999387423",
					SecID: ofxgo.SecurityID{
						UniqueID:     "899422348",
						UniqueIDType: "CUSIP",
					},
					DtPlaced:    *ofxgo.NewDateGMT(2017, 3, 24, 3, 19, 0, 0),
					Units:       oounits2,
					SubAcct:     ofxgo.SubAcctTypeCash,
					Duration:    ofxgo.DurationGoodTilCancel,
					Restriction: ofxgo.RestrictionAllOrNone,
					LimitPrice:  oolimitprice2,
				},
				BuyType: ofxgo.BuyTypeBuy,
			},
		},
	}
	expected.InvStmt = append(expected.InvStmt, &statementResponse)
	var yield1, yield2, strikeprice, parvalue ofxgo.Amount
	yield1.SetFrac64(192, 100)
	yield2.SetFrac64(17, 1)
	strikeprice.SetFrac64(79, 1)
	parvalue.SetFrac64(10029, 100)
	seclist := ofxgo.SecurityList{
		Securities: []ofxgo.Security{
			ofxgo.StockInfo{
				SecInfo: ofxgo.SecInfo{
					SecID: ofxgo.SecurityID{
						UniqueID:     "78462F103",
						UniqueIDType: "CUSIP",
					},
					SecName: "S&P 500 ETF",
					Ticker:  "SPY",
					FiID:    "99184",
				},
				Yield:      yield1,
				AssetClass: ofxgo.AssetClassOther,
			},
			ofxgo.OptInfo{
				SecInfo: ofxgo.SecInfo{
					SecID: ofxgo.SecurityID{
						UniqueID:     "129887339",
						UniqueIDType: "CUSIP",
					},
					SecName: "John's Fertilizer Puts",
					Ticker:  "FERTP",
					FiID:    "882919",
				},
				OptType:     ofxgo.OptTypePut,
				StrikePrice: strikeprice,
				DtExpire:    *ofxgo.NewDateGMT(2017, 9, 1, 0, 0, 0, 0),
				ShPerCtrct:  100,
				SecID: &ofxgo.SecurityID{
					UniqueID:     "983322180",
					UniqueIDType: "CUSIP",
				},
				AssetClass: ofxgo.AssetClassLargeStock,
			},
			ofxgo.StockInfo{
				SecInfo: ofxgo.SecInfo{
					SecID: ofxgo.SecurityID{
						UniqueID:     "899422348",
						UniqueIDType: "CUSIP",
					},
					SecName: "Whatchamacallit, Inc.",
					Ticker:  "WHAT",
					FiID:    "883897",
				},
				Yield:      yield2,
				AssetClass: ofxgo.AssetClassSmallStock,
			},
			ofxgo.MFInfo{
				SecInfo: ofxgo.SecInfo{
					SecID: ofxgo.SecurityID{
						UniqueID:     "922908645",
						UniqueIDType: "CUSIP",
					},
					SecName: "Mid-Cap Index Fund Admiral Shares",
					Ticker:  "VIMAX",
				},
			},
			ofxgo.DebtInfo{
				SecInfo: ofxgo.SecInfo{
					SecID: ofxgo.SecurityID{
						UniqueID:     "99182828",
						UniqueIDType: "CUSIP",
					},
					SecName: "Someone's Class B Debt",
				},
				ParValue:   parvalue,
				DebtType:   ofxgo.DebtTypeCoupon,
				DtCoupon:   ofxgo.NewDateGMT(2017, 9, 1, 0, 0, 0, 0),
				CouponFreq: ofxgo.CouponFreqQuarterly,
			},
			ofxgo.OtherInfo{
				SecInfo: ofxgo.SecInfo{
					SecID: ofxgo.SecurityID{
						UniqueID:     "88181818",
						UniqueIDType: "CUSIP",
					},
					SecName: "Foo Bar",
				},
				TypeDesc: "Don't know what this is",
			},
		},
	}
	expected.SecList = append(expected.SecList, &seclist)
	response, err := ofxgo.ParseResponse(responseReader)
	if err != nil {
		t.Fatalf("Unexpected error unmarshalling response: %s\n", err)
	}
	checkResponsesEqual(t, &expected, response)
}
func TestUnmarshalInvStatementResponse102(t *testing.T) {
	responseReader := strings.NewReader(`OFXHEADER: 100
DATA: OFXSGML
VERSION: 102
SECURITY: NONE
ENCODING: USASCII
CHARSET: 1252
COMPRESSION: NONE
OLDFILEUID: NONE
NEWFILEUID: NONE
 
  
   
    0
    INFO
   
   20170403120000
   ENG
   
    VV
    1000
   
   1000
  
 
 
  
   1283719872
   
    0
    INFO
   
   
    20170403120000
    USD
    
     www.exampletrader.com
     12341234
    
    
     20161206120000
     20170403120000
     
      
       
        12341234-20161207-1
        20161207120000
        20161208120000
       
       
        SPY161216C00226000
        CUSIP
       
       -1.0000
       0.3500
       8.8500
       0.2600
       200.8900
       CASH
       CASH
      
      SELLTOOPEN
      100
     
     
      
       12341234-20161215-1
       20161215120000
       20161220120000
      
      
       78462F10
       CUSIP
      
      ASSIGN
      -100.0000
      100
      CASH
     
     
      
       12341234-20161215-2
       20161215120000
       20161215120000
      
      
       SPY161216C00226000
       CUSIP
      
      ASSIGN
      1.0000
      100
      CASH
     
    
    
     
      
       
        04956010
        CUSIP
       
       CASH
       LONG
       100
       79.0000
       79000
       20170403120000
      
     
     
      
       
        36960410
        CUSIP
       
       CASH
       LONG
       100.00
       29.8700
       2987.00
       20170403120000
      
     
    
    
     0.0
     -0.00
     0.00
    
   
  
 
 
  
   
    
     
      78462F10
      CUSIP
     
     SPDR S&P 500 ETF TRUST
     SPY
    
   
   
    
     
      SPY161216C00226000
      CUSIP
     
     SPY Dec 16 2016 226.00 Call
     SPY   161216C00226000
    
    CALL
    226.00
    20161216120000
    100
   
  
 
`)
	var expected ofxgo.Response
	expected.Version = ofxgo.OfxVersion102
	expected.Signon.Status.Code = 0
	expected.Signon.Status.Severity = "INFO"
	expected.Signon.DtServer = *ofxgo.NewDateGMT(2017, 4, 3, 12, 0, 0, 0)
	expected.Signon.Language = "ENG"
	expected.Signon.Org = "VV"
	expected.Signon.Fid = "1000"
	// Ignored 1000
	var units1, unitprice1, commission1, fees1, total1, units2, units3 ofxgo.Amount
	units1.SetFrac64(-1, 1)
	unitprice1.SetFrac64(35, 100)
	commission1.SetFrac64(885, 100)
	fees1.SetFrac64(26, 100)
	total1.SetFrac64(20089, 100)
	units2.SetFrac64(-100, 1)
	units3.SetFrac64(1, 1)
	invtranlist := ofxgo.InvTranList{
		DtStart: *ofxgo.NewDateGMT(2016, 12, 6, 12, 0, 0, 0),
		DtEnd:   *ofxgo.NewDateGMT(2017, 4, 3, 12, 0, 0, 0),
		InvTransactions: []ofxgo.InvTransaction{
			ofxgo.SellOpt{
				InvSell: ofxgo.InvSell{
					InvTran: ofxgo.InvTran{
						FiTID:    "12341234-20161207-1",
						DtTrade:  *ofxgo.NewDateGMT(2016, 12, 7, 12, 0, 0, 0),
						DtSettle: ofxgo.NewDateGMT(2016, 12, 8, 12, 0, 0, 0),
					},
					SecID: ofxgo.SecurityID{
						UniqueID:     "SPY161216C00226000",
						UniqueIDType: "CUSIP",
					},
					Units:       units1,
					UnitPrice:   unitprice1,
					Commission:  commission1,
					Fees:        fees1,
					Total:       total1,
					SubAcctSec:  ofxgo.SubAcctTypeCash,
					SubAcctFund: ofxgo.SubAcctTypeCash,
				},
				OptSellType: ofxgo.OptSellTypeSellToOpen,
				ShPerCtrct:  100,
			},
			ofxgo.ClosureOpt{
				InvTran: ofxgo.InvTran{
					FiTID:    "12341234-20161215-1",
					DtTrade:  *ofxgo.NewDateGMT(2016, 12, 15, 12, 0, 0, 0),
					DtSettle: ofxgo.NewDateGMT(2016, 12, 20, 12, 0, 0, 0),
				},
				SecID: ofxgo.SecurityID{
					UniqueID:     "78462F10",
					UniqueIDType: "CUSIP",
				},
				OptAction:  ofxgo.OptActionAssign,
				Units:      units2,
				ShPerCtrct: 100,
				SubAcctSec: ofxgo.SubAcctTypeCash,
			},
			ofxgo.ClosureOpt{
				InvTran: ofxgo.InvTran{
					FiTID:    "12341234-20161215-2",
					DtTrade:  *ofxgo.NewDateGMT(2016, 12, 15, 12, 0, 0, 0),
					DtSettle: ofxgo.NewDateGMT(2016, 12, 15, 12, 0, 0, 0),
				},
				SecID: ofxgo.SecurityID{
					UniqueID:     "SPY161216C00226000",
					UniqueIDType: "CUSIP",
				},
				OptAction:  ofxgo.OptActionAssign,
				Units:      units3,
				ShPerCtrct: 100,
				SubAcctSec: ofxgo.SubAcctTypeCash,
			},
		},
	}
	var availcash, marginbalance, shortbalance ofxgo.Amount
	availcash.SetFrac64(0, 1)
	marginbalance.SetFrac64(-0, 1)
	shortbalance.SetFrac64(0, 1)
	invbalance := ofxgo.InvBalance{
		AvailCash:     availcash,
		MarginBalance: marginbalance,
		ShortBalance:  shortbalance,
	}
	var posunits1, posunitprice1, posmktval1, posunits2, posunitprice2, posmktval2 ofxgo.Amount
	posunits1.SetFrac64(100, 1)
	posunitprice1.SetFrac64(79, 1)
	posmktval1.SetFrac64(79000, 1)
	posunits2.SetFrac64(100, 1)
	posunitprice2.SetFrac64(2987, 100)
	posmktval2.SetFrac64(2987, 1)
	usd, err := ofxgo.NewCurrSymbol("USD")
	if err != nil {
		t.Fatalf("Unexpected error creating CurrSymbol for USD\n")
	}
	statementResponse := ofxgo.InvStatementResponse{
		TrnUID: "1283719872",
		Status: ofxgo.Status{
			Code:     0,
			Severity: "INFO",
		},
		DtAsOf: *ofxgo.NewDateGMT(2017, 4, 3, 12, 0, 0, 0),
		CurDef: *usd,
		InvAcctFrom: ofxgo.InvAcct{
			BrokerID: "www.exampletrader.com",
			AcctID:   "12341234",
		},
		InvTranList: &invtranlist,
		InvPosList: ofxgo.PositionList{
			ofxgo.StockPosition{
				InvPos: ofxgo.InvPosition{
					SecID: ofxgo.SecurityID{
						UniqueID:     "04956010",
						UniqueIDType: "CUSIP",
					},
					HeldInAcct:  ofxgo.SubAcctTypeCash,
					PosType:     ofxgo.PosTypeLong,
					Units:       posunits1,
					UnitPrice:   posunitprice1,
					MktVal:      posmktval1,
					DtPriceAsOf: *ofxgo.NewDateGMT(2017, 4, 3, 12, 0, 0, 0),
				},
			},
			ofxgo.StockPosition{
				InvPos: ofxgo.InvPosition{
					SecID: ofxgo.SecurityID{
						UniqueID:     "36960410",
						UniqueIDType: "CUSIP",
					},
					HeldInAcct:  ofxgo.SubAcctTypeCash,
					PosType:     ofxgo.PosTypeLong,
					Units:       posunits2,
					UnitPrice:   posunitprice2,
					MktVal:      posmktval2,
					DtPriceAsOf: *ofxgo.NewDateGMT(2017, 4, 3, 12, 0, 0, 0),
				},
			},
		},
		InvBal: &invbalance,
	}
	expected.InvStmt = append(expected.InvStmt, &statementResponse)
	var strikeprice ofxgo.Amount
	strikeprice.SetFrac64(226, 1)
	seclist := ofxgo.SecurityList{
		Securities: []ofxgo.Security{
			ofxgo.StockInfo{
				SecInfo: ofxgo.SecInfo{
					SecID: ofxgo.SecurityID{
						UniqueID:     "78462F10",
						UniqueIDType: "CUSIP",
					},
					SecName: "SPDR S&P 500 ETF TRUST",
					Ticker:  "SPY",
				},
			},
			ofxgo.OptInfo{
				SecInfo: ofxgo.SecInfo{
					SecID: ofxgo.SecurityID{
						UniqueID:     "SPY161216C00226000",
						UniqueIDType: "CUSIP",
					},
					SecName: "SPY Dec 16 2016 226.00 Call",
					Ticker:  "SPY   161216C00226000",
				},
				OptType:     ofxgo.OptTypeCall,
				StrikePrice: strikeprice,
				DtExpire:    *ofxgo.NewDateGMT(2016, 12, 16, 12, 0, 0, 0),
				ShPerCtrct:  100,
			},
		},
	}
	expected.SecList = append(expected.SecList, &seclist)
	response, err := ofxgo.ParseResponse(responseReader)
	if err != nil {
		t.Fatalf("Unexpected error unmarshalling response: %s\n", err)
	}
	checkResponsesEqual(t, &expected, response)
}
func TestUnmarshalInvTranList(t *testing.T) {
	input := `
	20170101000000
	20170331000000
	
		
			
				81818
				20170203
				20170207
			
			
				78462F103
				CUSIP
			
			100
			229.00
			9.00
			.26
			-22090.26
			CASH
			CASH
		
		101.2
	
	
		
			
				81818
				20170203
				Something to make a memo about
			
			
				78462F103
				CUSIP
			
			100
			229.00
			-22090.26
			CASH
			CASH
		
		BUYTOOPEN
		100
	
	
		
			129837-1111
			20170203
		
		
			78462F103
			CUSIP
		
		0.26
		CASH
		CASH
	
	
		
			129837-1112
			20170203
		
		
			78462F103
			CUSIP
		
		2300
		CASH
		CASH
	
	
		
			129837-1112
			20170203
		
		2300
		CASH
		CASH
	
	
		
			
				81818
				20170203
			
			
				78462F103
				CUSIP
			
			100
			229.00
			-22090.26
			CASH
			CASH
		
	
	
		
			129837-1112
			20170203
		
		2300
		CASH
	
	
		
			
				129837-1111
				20170203
			
			
				78462F103
				CUSIP
			
			100
			229.00
			-22090.26
			CASH
			CASH
		
		SELL
	
	
		
			129837-1111
			20170203
		
		
			78462F103
			CUSIP
		
		2300.00
		CASH
		CASH
	
	
		
			129837-1111
			20170203
		
		
			78462F103
			CUSIP
		
		CASH
		100
		200
		2
		1
	
	
		
			
				129837-1111
				20170203
			
			
				78462F103
				CUSIP
			
			100
			229.00
			-22090.26
			CASH
			CASH
		
	
`
	var units1, unitprice1, commission1, fees1, total1, accrdint, total2, oldunits1, newunits1 ofxgo.Amount
	units1.SetFrac64(100, 1)
	unitprice1.SetFrac64(229, 1)
	commission1.SetFrac64(9, 1)
	fees1.SetFrac64(26, 100)
	total1.SetFrac64(-2209026, 100)
	accrdint.SetFrac64(1012, 10)
	total2.SetFrac64(2300, 1)
	oldunits1.SetFrac64(100, 1)
	newunits1.SetFrac64(200, 1)
	expected := ofxgo.InvTranList{
		DtStart: *ofxgo.NewDateGMT(2017, 1, 1, 0, 0, 0, 0),
		DtEnd:   *ofxgo.NewDateGMT(2017, 3, 31, 0, 0, 0, 0),
		InvTransactions: []ofxgo.InvTransaction{
			ofxgo.BuyDebt{
				InvBuy: ofxgo.InvBuy{
					InvTran: ofxgo.InvTran{
						FiTID:    "81818",
						DtTrade:  *ofxgo.NewDateGMT(2017, 2, 3, 0, 0, 0, 0),
						DtSettle: ofxgo.NewDateGMT(2017, 2, 7, 0, 0, 0, 0),
					},
					SecID: ofxgo.SecurityID{
						UniqueID:     "78462F103",
						UniqueIDType: "CUSIP",
					},
					Units:       units1,
					UnitPrice:   unitprice1,
					Commission:  commission1,
					Fees:        fees1,
					Total:       total1,
					SubAcctSec:  ofxgo.SubAcctTypeCash,
					SubAcctFund: ofxgo.SubAcctTypeCash,
				},
				AccrdInt: accrdint,
			},
			ofxgo.BuyOpt{
				InvBuy: ofxgo.InvBuy{
					InvTran: ofxgo.InvTran{
						FiTID:   "81818",
						DtTrade: *ofxgo.NewDateGMT(2017, 2, 3, 0, 0, 0, 0),
						Memo:    "Something to make a memo about",
					},
					SecID: ofxgo.SecurityID{
						UniqueID:     "78462F103",
						UniqueIDType: "CUSIP",
					},
					Units:       units1,
					UnitPrice:   unitprice1,
					Total:       total1,
					SubAcctSec:  ofxgo.SubAcctTypeCash,
					SubAcctFund: ofxgo.SubAcctTypeCash,
				},
				OptBuyType: ofxgo.OptBuyTypeBuyToOpen,
				ShPerCtrct: 100,
			},
			ofxgo.InvExpense{
				InvTran: ofxgo.InvTran{
					FiTID:   "129837-1111",
					DtTrade: *ofxgo.NewDateGMT(2017, 2, 3, 0, 0, 0, 0),
				},
				SecID: ofxgo.SecurityID{
					UniqueID:     "78462F103",
					UniqueIDType: "CUSIP",
				},
				Total:       fees1,
				SubAcctSec:  ofxgo.SubAcctTypeCash,
				SubAcctFund: ofxgo.SubAcctTypeCash,
			},
			ofxgo.JrnlSec{
				InvTran: ofxgo.InvTran{
					FiTID:   "129837-1112",
					DtTrade: *ofxgo.NewDateGMT(2017, 2, 3, 0, 0, 0, 0),
				},
				SecID: ofxgo.SecurityID{
					UniqueID:     "78462F103",
					UniqueIDType: "CUSIP",
				},
				Units:       total2,
				SubAcctTo:   ofxgo.SubAcctTypeCash,
				SubAcctFrom: ofxgo.SubAcctTypeCash,
			},
			ofxgo.JrnlFund{
				InvTran: ofxgo.InvTran{
					FiTID:   "129837-1112",
					DtTrade: *ofxgo.NewDateGMT(2017, 2, 3, 0, 0, 0, 0),
				},
				Total:       total2,
				SubAcctTo:   ofxgo.SubAcctTypeCash,
				SubAcctFrom: ofxgo.SubAcctTypeCash,
			},
			ofxgo.BuyOther{
				InvBuy: ofxgo.InvBuy{
					InvTran: ofxgo.InvTran{
						FiTID:   "81818",
						DtTrade: *ofxgo.NewDateGMT(2017, 2, 3, 0, 0, 0, 0),
					},
					SecID: ofxgo.SecurityID{
						UniqueID:     "78462F103",
						UniqueIDType: "CUSIP",
					},
					Units:       units1,
					UnitPrice:   unitprice1,
					Total:       total1,
					SubAcctSec:  ofxgo.SubAcctTypeCash,
					SubAcctFund: ofxgo.SubAcctTypeCash,
				},
			},
			ofxgo.MarginInterest{
				InvTran: ofxgo.InvTran{
					FiTID:   "129837-1112",
					DtTrade: *ofxgo.NewDateGMT(2017, 2, 3, 0, 0, 0, 0),
				},
				Total:       total2,
				SubAcctFund: ofxgo.SubAcctTypeCash,
			},
			ofxgo.SellDebt{
				InvSell: ofxgo.InvSell{
					InvTran: ofxgo.InvTran{
						FiTID:   "129837-1111",
						DtTrade: *ofxgo.NewDateGMT(2017, 2, 3, 0, 0, 0, 0),
					},
					SecID: ofxgo.SecurityID{
						UniqueID:     "78462F103",
						UniqueIDType: "CUSIP",
					},
					Units:       units1,
					UnitPrice:   unitprice1,
					Total:       total1,
					SubAcctSec:  ofxgo.SubAcctTypeCash,
					SubAcctFund: ofxgo.SubAcctTypeCash,
				},
				SellReason: ofxgo.SellReasonSell,
			},
			ofxgo.RetOfCap{
				InvTran: ofxgo.InvTran{
					FiTID:   "129837-1111",
					DtTrade: *ofxgo.NewDateGMT(2017, 2, 3, 0, 0, 0, 0),
				},
				SecID: ofxgo.SecurityID{
					UniqueID:     "78462F103",
					UniqueIDType: "CUSIP",
				},
				Total:       total2,
				SubAcctSec:  ofxgo.SubAcctTypeCash,
				SubAcctFund: ofxgo.SubAcctTypeCash,
			},
			ofxgo.Split{
				InvTran: ofxgo.InvTran{
					FiTID:   "129837-1111",
					DtTrade: *ofxgo.NewDateGMT(2017, 2, 3, 0, 0, 0, 0),
				},
				SecID: ofxgo.SecurityID{
					UniqueID:     "78462F103",
					UniqueIDType: "CUSIP",
				},
				SubAcctSec:  ofxgo.SubAcctTypeCash,
				OldUnits:    oldunits1,
				NewUnits:    newunits1,
				Numerator:   2,
				Denominator: 1,
			},
			ofxgo.SellOther{
				InvSell: ofxgo.InvSell{
					InvTran: ofxgo.InvTran{
						FiTID:   "129837-1111",
						DtTrade: *ofxgo.NewDateGMT(2017, 2, 3, 0, 0, 0, 0),
					},
					SecID: ofxgo.SecurityID{
						UniqueID:     "78462F103",
						UniqueIDType: "CUSIP",
					},
					Units:       units1,
					UnitPrice:   unitprice1,
					Total:       total1,
					SubAcctSec:  ofxgo.SubAcctTypeCash,
					SubAcctFund: ofxgo.SubAcctTypeCash,
				},
			},
		},
	}
	var actual ofxgo.InvTranList
	err := xml.Unmarshal([]byte(input), &actual)
	if err != nil {
		t.Fatalf("Unexpected error unmarshalling InvTranList: %s\n", err)
	}
	checkEqual(t, "InvTranList", reflect.ValueOf(&expected), reflect.ValueOf(&actual))
}
func TestUnmarshalPositionList(t *testing.T) {
	input := `
	
		
			
				78462F103
				CUSIP
			
			CASH
			LONG
			1
			3
			300
			20170331160000
		
	
	
		
			
				78462F103
				CUSIP
			
			CASH
			SHORT
			200
			235.74
			47148.00
			20170331160000
			Price as of previous close
		
		Y
	
	
		
			
				129887339
				CUSIP
			
			CASH
			LONG
			1
			3
			300
			20170331160000
		
	
	
		
			
				129887339
				CUSIP
			
			CASH
			LONG
			1
			3
			300
			20170331160000
		
	
	
		
			
				78462F103
				CUSIP
			
			CASH
			LONG
			200
			235.74
			47148.00
			20170331160000
			Price as of previous close
		
		Y
		N
	
`
	var posunits1, posunitprice1, posmktval1, posunits2, posunitprice2, posmktval2 ofxgo.Amount
	posunits1.SetFrac64(200, 1)
	posunitprice1.SetFrac64(23574, 100)
	posmktval1.SetFrac64(47148, 1)
	posunits2.SetFrac64(1, 1)
	posunitprice2.SetFrac64(3, 1)
	posmktval2.SetFrac64(300, 1)
	expected := ofxgo.PositionList{
		ofxgo.OtherPosition{
			InvPos: ofxgo.InvPosition{
				SecID: ofxgo.SecurityID{
					UniqueID:     "78462F103",
					UniqueIDType: "CUSIP",
				},
				HeldInAcct:  ofxgo.SubAcctTypeCash,
				PosType:     ofxgo.PosTypeLong,
				Units:       posunits2,
				UnitPrice:   posunitprice2,
				MktVal:      posmktval2,
				DtPriceAsOf: *ofxgo.NewDateGMT(2017, 3, 31, 16, 0, 0, 0),
			},
		},
		ofxgo.StockPosition{
			InvPos: ofxgo.InvPosition{
				SecID: ofxgo.SecurityID{
					UniqueID:     "78462F103",
					UniqueIDType: "CUSIP",
				},
				HeldInAcct:  ofxgo.SubAcctTypeCash,
				PosType:     ofxgo.PosTypeShort,
				Units:       posunits1,
				UnitPrice:   posunitprice1,
				MktVal:      posmktval1,
				DtPriceAsOf: *ofxgo.NewDateGMT(2017, 3, 31, 16, 0, 0, 0),
				Memo:        "Price as of previous close",
			},
			ReinvDiv: true,
		},
		ofxgo.DebtPosition{
			InvPos: ofxgo.InvPosition{
				SecID: ofxgo.SecurityID{
					UniqueID:     "129887339",
					UniqueIDType: "CUSIP",
				},
				HeldInAcct:  ofxgo.SubAcctTypeCash,
				PosType:     ofxgo.PosTypeLong,
				Units:       posunits2,
				UnitPrice:   posunitprice2,
				MktVal:      posmktval2,
				DtPriceAsOf: *ofxgo.NewDateGMT(2017, 3, 31, 16, 0, 0, 0),
			},
		},
		ofxgo.OptPosition{
			InvPos: ofxgo.InvPosition{
				SecID: ofxgo.SecurityID{
					UniqueID:     "129887339",
					UniqueIDType: "CUSIP",
				},
				HeldInAcct:  ofxgo.SubAcctTypeCash,
				PosType:     ofxgo.PosTypeLong,
				Units:       posunits2,
				UnitPrice:   posunitprice2,
				MktVal:      posmktval2,
				DtPriceAsOf: *ofxgo.NewDateGMT(2017, 3, 31, 16, 0, 0, 0),
			},
		},
		ofxgo.MFPosition{
			InvPos: ofxgo.InvPosition{
				SecID: ofxgo.SecurityID{
					UniqueID:     "78462F103",
					UniqueIDType: "CUSIP",
				},
				HeldInAcct:  ofxgo.SubAcctTypeCash,
				PosType:     ofxgo.PosTypeLong,
				Units:       posunits1,
				UnitPrice:   posunitprice1,
				MktVal:      posmktval1,
				DtPriceAsOf: *ofxgo.NewDateGMT(2017, 3, 31, 16, 0, 0, 0),
				Memo:        "Price as of previous close",
			},
			ReinvDiv: true,
			ReinvCG:  false,
		},
	}
	var actual ofxgo.PositionList
	err := xml.Unmarshal([]byte(input), &actual)
	if err != nil {
		t.Fatalf("Unexpected error unmarshalling PositionList: %s\n", err)
	}
	checkEqual(t, "PositionList", reflect.ValueOf(&expected), reflect.ValueOf(&actual))
}
func TestUnmarshalOOList(t *testing.T) {
	input := `
	
		
			76464632
			
				922908645
				CUSIP
			
			20170310124445
			10
			CASH
			DAY
			NONE
		
		Y
	
	
		
			76464632
			
				922908645
				CUSIP
			
			20170310124445
			10
			CASH
			GOODTILCANCEL
			NONE
			168.50
		
		BUY
		SHARES
	
	
		
			999387423
			
				899422348
				CUSIP
			
			20170324031900
			25
			CASH
			GOODTILCANCEL
			ALLORNONE
			19.75
		
		BUYTOCLOSE
	
	
		
			999387423
			
				899422348
				CUSIP
			
			20170324031900
			25
			CASH
			GOODTILCANCEL
			ALLORNONE
			19.75
		
		BUY
	
	
		
			999387423
			
				899422348
				CUSIP
			
			20170324031900
			25
			CASH
			GOODTILCANCEL
			ALLORNONE
			19.75
		
		CURRENCY
	
	
		
			999387423
			
				899422348
				CUSIP
			
			20170324031900
			25
			CASH
			GOODTILCANCEL
			ALLORNONE
		
	
	
		
			999387423
			
				899422348
				CUSIP
			
			20170324031900
			25
			CASH
			GOODTILCANCEL
			ALLORNONE
		
		SELLSHORT
		SHARES
		
		Y
	
	
		
			999387423
			
				899422348
				CUSIP
			
			20170324031900
			25
			CASH
			GOODTILCANCEL
			ALLORNONE
		
		SELLTOOPEN
	
	
		
			999387423
			
				899422348
				CUSIP
			
			20170324031900
			25
			CASH
			GOODTILCANCEL
			ALLORNONE
		
		SHARES
	
	
		
			999387423
			
				899422348
				CUSIP
			
			20170324031900
			25
			CASH
			GOODTILCANCEL
			ALLORNONE
		
		SELL
	
	
		
			999387423
			
				899422348
				CUSIP
			
			20170324031900
			25
			CASH
			GOODTILCANCEL
			ALLORNONE
		
		
			899422389
			CUSIP
		
		CURRENCY
		N
	
`
	var oounits1, oolimitprice1, oounits2, oolimitprice2 ofxgo.Amount
	oounits1.SetFrac64(10, 1)
	oolimitprice1.SetFrac64(16850, 100)
	oounits2.SetFrac64(25, 1)
	oolimitprice2.SetFrac64(1975, 100)
	expected := ofxgo.OOList{
		ofxgo.OOBuyDebt{
			OO: ofxgo.OO{
				FiTID: "76464632",
				SecID: ofxgo.SecurityID{
					UniqueID:     "922908645",
					UniqueIDType: "CUSIP",
				},
				DtPlaced:    *ofxgo.NewDateGMT(2017, 3, 10, 12, 44, 45, 0),
				Units:       oounits1,
				SubAcct:     ofxgo.SubAcctTypeCash,
				Duration:    ofxgo.DurationDay,
				Restriction: ofxgo.RestrictionNone,
			},
			Auction: true,
		},
		ofxgo.OOBuyMF{
			OO: ofxgo.OO{
				FiTID: "76464632",
				SecID: ofxgo.SecurityID{
					UniqueID:     "922908645",
					UniqueIDType: "CUSIP",
				},
				DtPlaced:    *ofxgo.NewDateGMT(2017, 3, 10, 12, 44, 45, 0),
				Units:       oounits1,
				SubAcct:     ofxgo.SubAcctTypeCash,
				Duration:    ofxgo.DurationGoodTilCancel,
				Restriction: ofxgo.RestrictionNone,
				LimitPrice:  oolimitprice1,
			},
			BuyType:  ofxgo.BuyTypeBuy,
			UnitType: ofxgo.UnitTypeShares,
		},
		ofxgo.OOBuyOpt{
			OO: ofxgo.OO{
				FiTID: "999387423",
				SecID: ofxgo.SecurityID{
					UniqueID:     "899422348",
					UniqueIDType: "CUSIP",
				},
				DtPlaced:    *ofxgo.NewDateGMT(2017, 3, 24, 3, 19, 0, 0),
				Units:       oounits2,
				SubAcct:     ofxgo.SubAcctTypeCash,
				Duration:    ofxgo.DurationGoodTilCancel,
				Restriction: ofxgo.RestrictionAllOrNone,
				LimitPrice:  oolimitprice2,
			},
			OptBuyType: ofxgo.OptBuyTypeBuyToClose,
		},
		ofxgo.OOBuyStock{
			OO: ofxgo.OO{
				FiTID: "999387423",
				SecID: ofxgo.SecurityID{
					UniqueID:     "899422348",
					UniqueIDType: "CUSIP",
				},
				DtPlaced:    *ofxgo.NewDateGMT(2017, 3, 24, 3, 19, 0, 0),
				Units:       oounits2,
				SubAcct:     ofxgo.SubAcctTypeCash,
				Duration:    ofxgo.DurationGoodTilCancel,
				Restriction: ofxgo.RestrictionAllOrNone,
				LimitPrice:  oolimitprice2,
			},
			BuyType: ofxgo.BuyTypeBuy,
		},
		ofxgo.OOBuyOther{
			OO: ofxgo.OO{
				FiTID: "999387423",
				SecID: ofxgo.SecurityID{
					UniqueID:     "899422348",
					UniqueIDType: "CUSIP",
				},
				DtPlaced:    *ofxgo.NewDateGMT(2017, 3, 24, 3, 19, 0, 0),
				Units:       oounits2,
				SubAcct:     ofxgo.SubAcctTypeCash,
				Duration:    ofxgo.DurationGoodTilCancel,
				Restriction: ofxgo.RestrictionAllOrNone,
				LimitPrice:  oolimitprice2,
			},
			UnitType: ofxgo.UnitTypeCurrency,
		},
		ofxgo.OOSellDebt{
			OO: ofxgo.OO{
				FiTID: "999387423",
				SecID: ofxgo.SecurityID{
					UniqueID:     "899422348",
					UniqueIDType: "CUSIP",
				},
				DtPlaced:    *ofxgo.NewDateGMT(2017, 3, 24, 3, 19, 0, 0),
				Units:       oounits2,
				SubAcct:     ofxgo.SubAcctTypeCash,
				Duration:    ofxgo.DurationGoodTilCancel,
				Restriction: ofxgo.RestrictionAllOrNone,
			},
		},
		ofxgo.OOSellMF{
			OO: ofxgo.OO{
				FiTID: "999387423",
				SecID: ofxgo.SecurityID{
					UniqueID:     "899422348",
					UniqueIDType: "CUSIP",
				},
				DtPlaced:    *ofxgo.NewDateGMT(2017, 3, 24, 3, 19, 0, 0),
				Units:       oounits2,
				SubAcct:     ofxgo.SubAcctTypeCash,
				Duration:    ofxgo.DurationGoodTilCancel,
				Restriction: ofxgo.RestrictionAllOrNone,
			},
			SellType: ofxgo.SellTypeSellShort,
			UnitType: ofxgo.UnitTypeShares,
			SellAll:  true,
		},
		ofxgo.OOSellOpt{
			OO: ofxgo.OO{
				FiTID: "999387423",
				SecID: ofxgo.SecurityID{
					UniqueID:     "899422348",
					UniqueIDType: "CUSIP",
				},
				DtPlaced:    *ofxgo.NewDateGMT(2017, 3, 24, 3, 19, 0, 0),
				Units:       oounits2,
				SubAcct:     ofxgo.SubAcctTypeCash,
				Duration:    ofxgo.DurationGoodTilCancel,
				Restriction: ofxgo.RestrictionAllOrNone,
			},
			OptSellType: ofxgo.OptSellTypeSellToOpen,
		},
		ofxgo.OOSellOther{
			OO: ofxgo.OO{
				FiTID: "999387423",
				SecID: ofxgo.SecurityID{
					UniqueID:     "899422348",
					UniqueIDType: "CUSIP",
				},
				DtPlaced:    *ofxgo.NewDateGMT(2017, 3, 24, 3, 19, 0, 0),
				Units:       oounits2,
				SubAcct:     ofxgo.SubAcctTypeCash,
				Duration:    ofxgo.DurationGoodTilCancel,
				Restriction: ofxgo.RestrictionAllOrNone,
			},
			UnitType: ofxgo.UnitTypeShares,
		},
		ofxgo.OOSellStock{
			OO: ofxgo.OO{
				FiTID: "999387423",
				SecID: ofxgo.SecurityID{
					UniqueID:     "899422348",
					UniqueIDType: "CUSIP",
				},
				DtPlaced:    *ofxgo.NewDateGMT(2017, 3, 24, 3, 19, 0, 0),
				Units:       oounits2,
				SubAcct:     ofxgo.SubAcctTypeCash,
				Duration:    ofxgo.DurationGoodTilCancel,
				Restriction: ofxgo.RestrictionAllOrNone,
			},
			SellType: ofxgo.SellTypeSell,
		},
		ofxgo.OOSwitchMF{
			OO: ofxgo.OO{
				FiTID: "999387423",
				SecID: ofxgo.SecurityID{
					UniqueID:     "899422348",
					UniqueIDType: "CUSIP",
				},
				DtPlaced:    *ofxgo.NewDateGMT(2017, 3, 24, 3, 19, 0, 0),
				Units:       oounits2,
				SubAcct:     ofxgo.SubAcctTypeCash,
				Duration:    ofxgo.DurationGoodTilCancel,
				Restriction: ofxgo.RestrictionAllOrNone,
			},
			SecID: ofxgo.SecurityID{
				UniqueID:     "899422389",
				UniqueIDType: "CUSIP",
			},
			UnitType:  ofxgo.UnitTypeCurrency,
			SwitchAll: false,
		},
	}
	var actual ofxgo.OOList
	err := xml.Unmarshal([]byte(input), &actual)
	if err != nil {
		t.Fatalf("Unexpected error unmarshalling OOList: %s\n", err)
	}
	checkEqual(t, "OOList", reflect.ValueOf(&expected), reflect.ValueOf(&actual))
}