@barchart/portfolio-api-common 1.0.40 → 1.0.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/data/InstrumentType.js +11 -5
- package/lib/processing/PositionGroup.js +34 -5
- package/lib/processing/PositionItem.js +11 -3
- package/lib/serialization/PositionSchema.js +5 -3
- package/package.json +1 -1
- package/test/SpecRunner.js +69 -35
- package/test/specs/processing/PositionContainerSpec.js +22 -25
|
@@ -10,16 +10,22 @@ module.exports = (() => {
|
|
|
10
10
|
* @public
|
|
11
11
|
* @extends {Enum}
|
|
12
12
|
* @param {String} description
|
|
13
|
+
* @param {String} alternateDescription
|
|
13
14
|
* @param {String} code
|
|
14
15
|
* @param {Boolean} canReinvest
|
|
15
16
|
*/
|
|
16
17
|
class InstrumentType extends Enum {
|
|
17
|
-
constructor(code, description, canReinvest) {
|
|
18
|
+
constructor(code, description, alternateDescription, canReinvest) {
|
|
18
19
|
super(code, description);
|
|
19
20
|
|
|
21
|
+
this._alternateDescription = alternateDescription;
|
|
20
22
|
this._canReinvest = canReinvest;
|
|
21
23
|
}
|
|
22
24
|
|
|
25
|
+
get alternateDescription() {
|
|
26
|
+
return this._alternateDescription;
|
|
27
|
+
}
|
|
28
|
+
|
|
23
29
|
/**
|
|
24
30
|
* Indicates if the instrument type allows automatic reinvestment.
|
|
25
31
|
*
|
|
@@ -74,10 +80,10 @@ module.exports = (() => {
|
|
|
74
80
|
}
|
|
75
81
|
}
|
|
76
82
|
|
|
77
|
-
const cash = new InstrumentType('CASH', 'cash', false);
|
|
78
|
-
const equity = new InstrumentType('EQUITY', 'equity', true);
|
|
79
|
-
const fund = new InstrumentType('FUND', 'mutual fund', true);
|
|
80
|
-
const other = new InstrumentType('OTHER', 'other', false);
|
|
83
|
+
const cash = new InstrumentType('CASH', 'cash', 'Cash', false);
|
|
84
|
+
const equity = new InstrumentType('EQUITY', 'equity', 'Equities', true);
|
|
85
|
+
const fund = new InstrumentType('FUND', 'mutual fund', 'Funds', true);
|
|
86
|
+
const other = new InstrumentType('OTHER', 'other', 'Other', false);
|
|
81
87
|
|
|
82
88
|
return InstrumentType;
|
|
83
89
|
})();
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const assert = require('@barchart/common-js/lang/assert'),
|
|
2
|
+
Decimal = require('@barchart/common-js/lang/Decimal'),
|
|
2
3
|
is = require('@barchart/common-js/lang/is');
|
|
3
4
|
|
|
4
5
|
module.exports = (() => {
|
|
@@ -18,16 +19,21 @@ module.exports = (() => {
|
|
|
18
19
|
|
|
19
20
|
this._data.description = this._description;
|
|
20
21
|
|
|
21
|
-
this._data.previous = null;
|
|
22
22
|
this._data.current = null;
|
|
23
|
+
this._data.previous = null;
|
|
24
|
+
|
|
25
|
+
this._data.basis = null;
|
|
26
|
+
this._data.market = null;
|
|
23
27
|
|
|
24
28
|
this._items.forEach((item) => {
|
|
25
|
-
item.registerPriceChangeHandler((
|
|
29
|
+
item.registerPriceChangeHandler((data, sender) => {
|
|
26
30
|
if (this._single) {
|
|
27
|
-
data.current =
|
|
31
|
+
data.current = data.current;
|
|
28
32
|
} else {
|
|
29
33
|
data.current = null;
|
|
30
34
|
}
|
|
35
|
+
|
|
36
|
+
calculateVariablePriceData(this, item, price);
|
|
31
37
|
});
|
|
32
38
|
});
|
|
33
39
|
|
|
@@ -46,6 +52,10 @@ module.exports = (() => {
|
|
|
46
52
|
return this._items;
|
|
47
53
|
}
|
|
48
54
|
|
|
55
|
+
get single() {
|
|
56
|
+
return this._single;
|
|
57
|
+
}
|
|
58
|
+
|
|
49
59
|
toString() {
|
|
50
60
|
return '[PositionGroup]';
|
|
51
61
|
}
|
|
@@ -55,10 +65,29 @@ module.exports = (() => {
|
|
|
55
65
|
const items = group._items;
|
|
56
66
|
const data = group._data;
|
|
57
67
|
|
|
58
|
-
|
|
68
|
+
let updates;
|
|
69
|
+
|
|
70
|
+
if (group.single) {
|
|
71
|
+
const item = items[0];
|
|
59
72
|
|
|
60
|
-
|
|
73
|
+
updates.basis = item.basis;
|
|
74
|
+
} else {
|
|
75
|
+
updates = items.reduce(function(updates, item) {
|
|
76
|
+
const position = item.position;
|
|
77
|
+
const snapshot = item.position.snapshot;
|
|
78
|
+
|
|
79
|
+
updates.value = updates.basis.add(snapshot.basis);
|
|
80
|
+
|
|
81
|
+
return updates;
|
|
82
|
+
}, {
|
|
83
|
+
basis: Decimal.ZERO
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
data.basis = updates.basis;
|
|
88
|
+
}
|
|
61
89
|
|
|
90
|
+
function calculateVariablePriceData(group, item, price) {
|
|
62
91
|
|
|
63
92
|
}
|
|
64
93
|
|
|
@@ -14,7 +14,13 @@ module.exports = (() => {
|
|
|
14
14
|
this._position = position;
|
|
15
15
|
this._summaries = summaries || [ ];
|
|
16
16
|
|
|
17
|
-
this.
|
|
17
|
+
this._data = { };
|
|
18
|
+
|
|
19
|
+
this._data.current = null;
|
|
20
|
+
this._data.previous = position.previous || null;
|
|
21
|
+
|
|
22
|
+
const snapshot = this._position.snapshot;
|
|
23
|
+
|
|
18
24
|
this._priceChangeEvent = new Event(this);
|
|
19
25
|
}
|
|
20
26
|
|
|
@@ -31,8 +37,10 @@ module.exports = (() => {
|
|
|
31
37
|
}
|
|
32
38
|
|
|
33
39
|
setPrice(price) {
|
|
34
|
-
if (this.
|
|
35
|
-
this.
|
|
40
|
+
if (this._data.price !== price) {
|
|
41
|
+
this._data.price = price;
|
|
42
|
+
|
|
43
|
+
this._priceChangeEvent.fire(this._data);
|
|
36
44
|
}
|
|
37
45
|
}
|
|
38
46
|
|
|
@@ -6,7 +6,8 @@ const assert = require('@barchart/common-js/lang/assert'),
|
|
|
6
6
|
Schema = require('@barchart/common-js/serialization/json/Schema'),
|
|
7
7
|
SchemaBuilder = require('@barchart/common-js/serialization/json/builders/SchemaBuilder');
|
|
8
8
|
|
|
9
|
-
const
|
|
9
|
+
const InstrumentType = require('./../data/InstrumentType'),
|
|
10
|
+
ValuationType = require('./../data/ValuationType');
|
|
10
11
|
|
|
11
12
|
module.exports = (() => {
|
|
12
13
|
'use strict';
|
|
@@ -67,7 +68,7 @@ module.exports = (() => {
|
|
|
67
68
|
.withField('sequence', DataType.NUMBER)
|
|
68
69
|
.withField('instrument.id', DataType.STRING)
|
|
69
70
|
.withField('instrument.name', DataType.STRING)
|
|
70
|
-
.withField('instrument.type', DataType.
|
|
71
|
+
.withField('instrument.type', DataType.forEnum(InstrumentType, 'InstrumentType'))
|
|
71
72
|
.withField('instrument.currency', DataType.forEnum(Currency, 'Currency'))
|
|
72
73
|
.withField('instrument.delist', DataType.DAY, true)
|
|
73
74
|
.withField('instrument.symbol.barchart', DataType.STRING, true)
|
|
@@ -99,7 +100,7 @@ module.exports = (() => {
|
|
|
99
100
|
.withField('sequence', DataType.NUMBER)
|
|
100
101
|
.withField('instrument.id', DataType.STRING)
|
|
101
102
|
.withField('instrument.name', DataType.STRING)
|
|
102
|
-
.withField('instrument.type', DataType.
|
|
103
|
+
.withField('instrument.type', DataType.forEnum(InstrumentType, 'InstrumentType'))
|
|
103
104
|
.withField('instrument.currency', DataType.forEnum(Currency, 'Currency'))
|
|
104
105
|
.withField('instrument.delist', DataType.DAY, true)
|
|
105
106
|
.withField('instrument.symbol.barchart', DataType.STRING, true)
|
|
@@ -117,6 +118,7 @@ module.exports = (() => {
|
|
|
117
118
|
.withField('snapshot.basis', DataType.DECIMAL)
|
|
118
119
|
.withField('snapshot.income', DataType.DECIMAL)
|
|
119
120
|
.withField('snapshot.value', DataType.DECIMAL)
|
|
121
|
+
.withField('previous', DataType.DECIMAL, true)
|
|
120
122
|
.schema
|
|
121
123
|
);
|
|
122
124
|
|
package/package.json
CHANGED
package/test/SpecRunner.js
CHANGED
|
@@ -653,6 +653,7 @@ module.exports = (() => {
|
|
|
653
653
|
|
|
654
654
|
},{"./PositionGroup":4,"./PositionGroupDefinition":5,"./PositionItem":6,"@barchart/common-js/collections/Tree":7,"@barchart/common-js/lang/array":14,"@barchart/common-js/lang/assert":15,"@barchart/common-js/lang/is":16}],4:[function(require,module,exports){
|
|
655
655
|
const assert = require('@barchart/common-js/lang/assert'),
|
|
656
|
+
Decimal = require('@barchart/common-js/lang/Decimal'),
|
|
656
657
|
is = require('@barchart/common-js/lang/is');
|
|
657
658
|
|
|
658
659
|
module.exports = (() => {
|
|
@@ -672,16 +673,21 @@ module.exports = (() => {
|
|
|
672
673
|
|
|
673
674
|
this._data.description = this._description;
|
|
674
675
|
|
|
675
|
-
this._data.previous = null;
|
|
676
676
|
this._data.current = null;
|
|
677
|
+
this._data.previous = null;
|
|
678
|
+
|
|
679
|
+
this._data.basis = null;
|
|
680
|
+
this._data.market = null;
|
|
677
681
|
|
|
678
682
|
this._items.forEach((item) => {
|
|
679
|
-
item.registerPriceChangeHandler((
|
|
683
|
+
item.registerPriceChangeHandler((data, sender) => {
|
|
680
684
|
if (this._single) {
|
|
681
|
-
data.current =
|
|
685
|
+
data.current = data.current;
|
|
682
686
|
} else {
|
|
683
687
|
data.current = null;
|
|
684
688
|
}
|
|
689
|
+
|
|
690
|
+
calculateVariablePriceData(this, item, price);
|
|
685
691
|
});
|
|
686
692
|
});
|
|
687
693
|
|
|
@@ -700,6 +706,10 @@ module.exports = (() => {
|
|
|
700
706
|
return this._items;
|
|
701
707
|
}
|
|
702
708
|
|
|
709
|
+
get single() {
|
|
710
|
+
return this._single;
|
|
711
|
+
}
|
|
712
|
+
|
|
703
713
|
toString() {
|
|
704
714
|
return '[PositionGroup]';
|
|
705
715
|
}
|
|
@@ -709,17 +719,36 @@ module.exports = (() => {
|
|
|
709
719
|
const items = group._items;
|
|
710
720
|
const data = group._data;
|
|
711
721
|
|
|
712
|
-
|
|
722
|
+
let updates;
|
|
713
723
|
|
|
714
|
-
|
|
724
|
+
if (group.single) {
|
|
725
|
+
const item = items[0];
|
|
715
726
|
|
|
727
|
+
updates.basis = item.basis;
|
|
728
|
+
} else {
|
|
729
|
+
updates = items.reduce(function(updates, item) {
|
|
730
|
+
const position = item.position;
|
|
731
|
+
const snapshot = item.position.snapshot;
|
|
732
|
+
|
|
733
|
+
updates.value = updates.basis.add(snapshot.basis);
|
|
734
|
+
|
|
735
|
+
return updates;
|
|
736
|
+
}, {
|
|
737
|
+
basis: Decimal.ZERO
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
data.basis = updates.basis;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
function calculateVariablePriceData(group, item, price) {
|
|
716
745
|
|
|
717
746
|
}
|
|
718
747
|
|
|
719
748
|
return PositionGroup;
|
|
720
749
|
})();
|
|
721
750
|
|
|
722
|
-
},{"@barchart/common-js/lang/assert":15,"@barchart/common-js/lang/is":16}],5:[function(require,module,exports){
|
|
751
|
+
},{"@barchart/common-js/lang/Decimal":11,"@barchart/common-js/lang/assert":15,"@barchart/common-js/lang/is":16}],5:[function(require,module,exports){
|
|
723
752
|
const assert = require('@barchart/common-js/lang/assert'),
|
|
724
753
|
is = require('@barchart/common-js/lang/is');
|
|
725
754
|
|
|
@@ -781,7 +810,13 @@ module.exports = (() => {
|
|
|
781
810
|
this._position = position;
|
|
782
811
|
this._summaries = summaries || [ ];
|
|
783
812
|
|
|
784
|
-
this.
|
|
813
|
+
this._data = { };
|
|
814
|
+
|
|
815
|
+
this._data.current = null;
|
|
816
|
+
this._data.previous = position.previous || null;
|
|
817
|
+
|
|
818
|
+
const snapshot = this._position.snapshot;
|
|
819
|
+
|
|
785
820
|
this._priceChangeEvent = new Event(this);
|
|
786
821
|
}
|
|
787
822
|
|
|
@@ -798,8 +833,10 @@ module.exports = (() => {
|
|
|
798
833
|
}
|
|
799
834
|
|
|
800
835
|
setPrice(price) {
|
|
801
|
-
if (this.
|
|
802
|
-
this.
|
|
836
|
+
if (this._data.price !== price) {
|
|
837
|
+
this._data.price = price;
|
|
838
|
+
|
|
839
|
+
this._priceChangeEvent.fire(this._data);
|
|
803
840
|
}
|
|
804
841
|
}
|
|
805
842
|
|
|
@@ -4992,12 +5029,31 @@ describe('After the PositionSummaryFrame enumeration is initialized', () => {
|
|
|
4992
5029
|
});
|
|
4993
5030
|
|
|
4994
5031
|
},{"./../../../lib/data/PositionSummaryFrame":1,"./../../../lib/data/TransactionType":2,"@barchart/common-js/lang/Day":10,"@barchart/common-js/lang/Decimal":11}],20:[function(require,module,exports){
|
|
5032
|
+
const Decimal = require('@barchart/common-js/lang/Decimal');
|
|
5033
|
+
|
|
4995
5034
|
const PositionContainer = require('./../../../lib/processing/PositionContainer'),
|
|
4996
5035
|
PositionGroupDefinition = require('./../../../lib/processing/PositionGroupDefinition');
|
|
4997
5036
|
|
|
4998
5037
|
describe('When a position container data is gathered', () => {
|
|
4999
5038
|
'use strict';
|
|
5000
5039
|
|
|
5040
|
+
let positionCounter = 0;
|
|
5041
|
+
|
|
5042
|
+
function getPosition(portfolio, symbol) {
|
|
5043
|
+
return {
|
|
5044
|
+
portfolio: portfolio,
|
|
5045
|
+
position: (positionCounter++).toString(),
|
|
5046
|
+
instrument: {
|
|
5047
|
+
symbol: {
|
|
5048
|
+
barchart: symbol
|
|
5049
|
+
}
|
|
5050
|
+
},
|
|
5051
|
+
snapshot: {
|
|
5052
|
+
basis: new Decimal(123)
|
|
5053
|
+
}
|
|
5054
|
+
}
|
|
5055
|
+
}
|
|
5056
|
+
|
|
5001
5057
|
describe('for two portfolios, each with the same position, and the second portfolio with an additonal position', () => {
|
|
5002
5058
|
let portfolios;
|
|
5003
5059
|
let positions;
|
|
@@ -5015,31 +5071,9 @@ describe('When a position container data is gathered', () => {
|
|
|
5015
5071
|
];
|
|
5016
5072
|
|
|
5017
5073
|
positions = [
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
instrument: {
|
|
5022
|
-
symbol: {
|
|
5023
|
-
barchart: 'AAPL'
|
|
5024
|
-
}
|
|
5025
|
-
},
|
|
5026
|
-
}, {
|
|
5027
|
-
portfolio: 'b',
|
|
5028
|
-
position: '2',
|
|
5029
|
-
instrument: {
|
|
5030
|
-
symbol: {
|
|
5031
|
-
barchart: 'AAPL'
|
|
5032
|
-
}
|
|
5033
|
-
}
|
|
5034
|
-
}, {
|
|
5035
|
-
portfolio: 'b',
|
|
5036
|
-
position: '3',
|
|
5037
|
-
instrument: {
|
|
5038
|
-
symbol: {
|
|
5039
|
-
barchart: 'TSLA'
|
|
5040
|
-
}
|
|
5041
|
-
}
|
|
5042
|
-
}
|
|
5074
|
+
getPosition('a', 'AAPL'),
|
|
5075
|
+
getPosition('b', 'AAPL'),
|
|
5076
|
+
getPosition('b', 'TSLA')
|
|
5043
5077
|
];
|
|
5044
5078
|
|
|
5045
5079
|
summaries = [ ];
|
|
@@ -5090,4 +5124,4 @@ describe('When a position container data is gathered', () => {
|
|
|
5090
5124
|
});
|
|
5091
5125
|
});
|
|
5092
5126
|
|
|
5093
|
-
},{"./../../../lib/processing/PositionContainer":3,"./../../../lib/processing/PositionGroupDefinition":5}]},{},[19,20]);
|
|
5127
|
+
},{"./../../../lib/processing/PositionContainer":3,"./../../../lib/processing/PositionGroupDefinition":5,"@barchart/common-js/lang/Decimal":11}]},{},[19,20]);
|
|
@@ -1,9 +1,28 @@
|
|
|
1
|
+
const Decimal = require('@barchart/common-js/lang/Decimal');
|
|
2
|
+
|
|
1
3
|
const PositionContainer = require('./../../../lib/processing/PositionContainer'),
|
|
2
4
|
PositionGroupDefinition = require('./../../../lib/processing/PositionGroupDefinition');
|
|
3
5
|
|
|
4
6
|
describe('When a position container data is gathered', () => {
|
|
5
7
|
'use strict';
|
|
6
8
|
|
|
9
|
+
let positionCounter = 0;
|
|
10
|
+
|
|
11
|
+
function getPosition(portfolio, symbol) {
|
|
12
|
+
return {
|
|
13
|
+
portfolio: portfolio,
|
|
14
|
+
position: (positionCounter++).toString(),
|
|
15
|
+
instrument: {
|
|
16
|
+
symbol: {
|
|
17
|
+
barchart: symbol
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
snapshot: {
|
|
21
|
+
basis: new Decimal(123)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
7
26
|
describe('for two portfolios, each with the same position, and the second portfolio with an additonal position', () => {
|
|
8
27
|
let portfolios;
|
|
9
28
|
let positions;
|
|
@@ -21,31 +40,9 @@ describe('When a position container data is gathered', () => {
|
|
|
21
40
|
];
|
|
22
41
|
|
|
23
42
|
positions = [
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
instrument: {
|
|
28
|
-
symbol: {
|
|
29
|
-
barchart: 'AAPL'
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
}, {
|
|
33
|
-
portfolio: 'b',
|
|
34
|
-
position: '2',
|
|
35
|
-
instrument: {
|
|
36
|
-
symbol: {
|
|
37
|
-
barchart: 'AAPL'
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}, {
|
|
41
|
-
portfolio: 'b',
|
|
42
|
-
position: '3',
|
|
43
|
-
instrument: {
|
|
44
|
-
symbol: {
|
|
45
|
-
barchart: 'TSLA'
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
43
|
+
getPosition('a', 'AAPL'),
|
|
44
|
+
getPosition('b', 'AAPL'),
|
|
45
|
+
getPosition('b', 'TSLA')
|
|
49
46
|
];
|
|
50
47
|
|
|
51
48
|
summaries = [ ];
|