-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathportfolio.go
81 lines (67 loc) · 1.54 KB
/
portfolio.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package main
// Portfolio represents a collection of outstanding positions
type Portfolio interface {
Symbols() Symbols
Position(s Symbol) float64
CashAmount() float64
Select(ss Symbols) Portfolio
AggregateEquivalents(market Market, model Model, selector PriceSelector) Portfolio
}
type portfolioImpl struct {
Cash float64
Assets map[Symbol]PortfolioAsset
}
func (p portfolioImpl) Symbols() Symbols {
ss := NewSymbols()
for s := range p.Assets {
ss = ss.Add(s)
}
return ss
}
func (p portfolioImpl) Position(s Symbol) float64 {
if a, ok := p.Assets[s]; ok {
return a.Position
}
return 0
}
func (p portfolioImpl) CashAmount() float64 {
return p.Cash
}
func (p portfolioImpl) Select(ss Symbols) Portfolio {
newP := portfolioImpl{
Cash: p.Cash,
Assets: make(map[Symbol]PortfolioAsset),
}
for s, a := range p.Assets {
if ss.Contains(s) {
newP.Assets[s] = a
}
}
return newP
}
func (p portfolioImpl) AggregateEquivalents(market Market, model Model, selector PriceSelector) Portfolio {
newP := portfolioImpl{
Cash: p.Cash,
Assets: make(map[Symbol]PortfolioAsset),
}
for s, a := range p.Assets {
newP.Assets[s] = a
}
for _, s := range model.Symbols().ToSlice() {
for _, e := range model.Equivalents(s).ToSlice() {
if !newP.Symbols().Contains(e) {
continue
}
newP.Assets[s] = PortfolioAsset{
Position: p.Assets[s].Position +
(p.Assets[e].Position*selector(market, e))/
selector(market, s),
}
delete(newP.Assets, e)
}
}
return newP
}
type PortfolioAsset struct {
Position float64
}