@millistream/millistream-widgets 1.0.0 → 1.0.3

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/README.md CHANGED
@@ -45,12 +45,66 @@ loadChart) {
45
45
  gridHorizontalLines: 0,
46
46
  gridHorizontalLinesStyle: 'normal',
47
47
  gridVerticalLines: 1,
48
- chartlen: '1y',
48
+ chartlen: '2d',
49
49
  dateformat: 'b dd',
50
50
  drawyaxis: true,
51
51
  fillchart: true,
52
52
  timeformat: 'HH:mm',
53
53
  streaming: pushapi,
54
+ fillchart: true,
55
+ timeformat: 'HH:mm',
56
+ streaming: pushapi,
57
+ instrumentStyle: {
58
+ color: '#f90',
59
+ backgroundLinearGradient: {
60
+ topColor: 'rgba(255,153,0,0.6)',
61
+ bottomColor: 'rgba(255,153,0,0.1)',
62
+ },
63
+ width: 1,
64
+ },
65
+ horizontalLegendStyle: {
66
+ fontSize: '11px',
67
+ fontFamily: 'Arial, Helvetica, sans-serif',
68
+ },
69
+ verticalLegendStyle: {
70
+ fontSize: '11px',
71
+ fontFamily: 'Arial, Helvetica, sans-serif',
72
+ },
73
+ tooltip: {
74
+ // @ts-ignore
75
+ formatter: function () {
76
+ // @ts-ignore
77
+ var date = formatDate(this.data.date, 'yyyy-mm-dd');
78
+ var time = '';
79
+ // @ts-ignore
80
+ if (this.chartType == 'trades') {
81
+ // @ts-ignore
82
+ var hour = this.data.date.getHours();
83
+ var minute = '';
84
+ // @ts-ignore
85
+ if (this.data.date.getMinutes() < 10) minute = '0';
86
+ // @ts-ignore
87
+ minute += this.data.date.getMinutes();
88
+ time = hour + ':' + minute;
89
+ }
90
+ // @ts-ignore
91
+ return (
92
+ '<span class="tooltip-name">' +
93
+ // @ts-ignore
94
+ this.name +
95
+ '</span><br>' +
96
+ // @ts-ignore
97
+ this.data.price +
98
+ ', ' +
99
+ // @ts-ignore
100
+ this.data.diff.toFixed(2) +
101
+ '%</br>' +
102
+ date +
103
+ ' ' +
104
+ time
105
+ );
106
+ },
107
+ },
54
108
  });
55
109
 
56
110
  })();
@@ -67,19 +121,6 @@ loadChart) {
67
121
  position: relative;
68
122
  }
69
123
 
70
- .millistream-chart {
71
- margin-bottom: 30px;
72
- }
73
-
74
- .millistream-chart-instrument {
75
- color: #f90;
76
- background-image: linear-gradient(
77
- rgba(255, 153, 0, 0.6),
78
- rgba(255, 153, 0, 0)
79
- );
80
- width: 2px;
81
- }
82
-
83
124
  .millistream-chart-tooltip {
84
125
  position: absolute;
85
126
  background: #ffffff;
@@ -88,7 +129,6 @@ loadChart) {
88
129
  font-family: Arial, Helvetica, sans-serif;
89
130
  font-size: 11px;
90
131
  padding: 2px;
91
- height: 14px;
92
132
  pointer-events: none;
93
133
  }
94
134
 
@@ -100,23 +140,6 @@ loadChart) {
100
140
  pointer-events: none;
101
141
  }
102
142
 
103
- .millistream-chart-x-legend {
104
- font-family: Arial, Helvetica, sans-serif;
105
- font-size: 11px;
106
- }
107
-
108
- .millistream-chart-y-legend {
109
- font-family: Arial, Helvetica, sans-serif;
110
- font-size: 11px;
111
- float: left;
112
- }
113
-
114
- .millistream-chart-y2-legend {
115
- font-family: Arial, Helvetica, sans-serif;
116
- font-size: 11px;
117
- float: right;
118
- }
119
-
120
143
  .millistream-chart-zoombox {
121
144
  position: absolute;
122
145
  background: rgb(255, 153, 0, 0.1);
@@ -129,4 +152,4 @@ Please refer to non npm-version documentation on widget customization.
129
152
  https://widgets.millistream.com/3.0.3/doc/widgets.html
130
153
 
131
154
  ## Support
132
- https://www.millistream.com
155
+ https://www.millistream.com
@@ -6,6 +6,7 @@ function Milli_Chart(settings) {
6
6
  _this.scaleinfoY = {};
7
7
  _this.scaleinfoY2 = {};
8
8
  _this.instruments = [];
9
+ _this.movingAverage = [];
9
10
  _this.settings = {
10
11
  adjusted: true,
11
12
  autodraw: true,
@@ -59,7 +60,8 @@ function Milli_Chart(settings) {
59
60
  arr: [],
60
61
  map: new Map()
61
62
  };
62
-
63
+ var m_analyzisMethod = new Map();
64
+ var m_analyzisIndex = 0;
63
65
  var m_resizing = {
64
66
  resizing: false,
65
67
  width: 0,
@@ -191,19 +193,6 @@ function Milli_Chart(settings) {
191
193
  // Discard the time and time-zone information.
192
194
  const utc1 = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate());
193
195
  const utc2 = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate());
194
- /*var start = new Date(utc1);
195
- var end = new Date(utc2);
196
- var days = 0;
197
- console.log(start, end, a, b);
198
- while (start < end) {
199
- console.log(start, end);
200
- if (start.getDay() != 0 && start.getDay() != 6)
201
- days++;
202
- start = new Date(start.getTime() + 86400000);
203
- }
204
-
205
- console.log(days, Math.floor((utc2 - utc1) / 86400000));
206
- return days;*/
207
196
  return Math.floor((utc2 - utc1) / 86400000); // ms per day
208
197
  }
209
198
 
@@ -422,7 +411,7 @@ function Milli_Chart(settings) {
422
411
  var data = _this.instruments[s][_this.scaleinfoY.type];
423
412
  if (_this.scaleinfoY.type != 'history') {
424
413
  if (_this.settings.chartlen == '1d' || _this.settings.chartlen == '0d' && !m_zoom.mousedown.timestamp) {
425
- firstvalue = parseFloat(_this.instruments[s].closeprice1d);
414
+ firstvalue = parseFloat(_this.instruments[s].closeprice1d) * _this.instruments[s].factor;
426
415
  }
427
416
  }
428
417
  var quantity = 0;
@@ -434,6 +423,7 @@ function Milli_Chart(settings) {
434
423
  quantity = data[i].quantity;
435
424
  }
436
425
  if (data[i].timestamp < _this.scaleinfoX.startTimeStamp) {
426
+ if (_this.scaleinfoY.type == 'history') firstvalue = price;
437
427
  continue;
438
428
  }
439
429
  if (data[i].timestamp > _this.scaleinfoX.endTimeStamp) {
@@ -446,11 +436,11 @@ function Milli_Chart(settings) {
446
436
  }
447
437
 
448
438
  if (firstvalue == null) {
449
- if (_this.scaleinfoY.type == 'history')
439
+ if (_this.scaleinfoY.type == 'history') {
450
440
  firstvalue = price;
451
- else {
441
+ } else {
452
442
  if (isToday(new Date(data[i].timestamp)) && !m_zoom.mousedown.timestamp) {
453
- firstvalue = parseFloat(_this.instruments[s].closeprice1d);
443
+ firstvalue = parseFloat(_this.instruments[s].closeprice1d) * _this.instruments[s].factor;
454
444
  } else
455
445
  firstvalue = price;
456
446
  }
@@ -465,7 +455,7 @@ function Milli_Chart(settings) {
465
455
  if (_this.scaleinfoY.highLowerChart == null || _this.scaleinfoY.highLowerChart < quantity) _this.scaleinfoY.highLowerChart = quantity;
466
456
  }
467
457
  if (_this.settings.chartlen == '1d' || _this.settings.chartlen == '0d') { // if closeprice is used calch high/low on it
468
- var cp = parseFloat(_this.instruments[s].closeprice1d);
458
+ var cp = parseFloat(_this.instruments[s].closeprice1d) * _this.instruments[s].factor;
469
459
  if (_this.scaleinfoY.lowValue > cp) _this.scaleinfoY.lowValue = cp;
470
460
  else
471
461
  if (_this.scaleinfoY.highValue < cp) _this.scaleinfoY.highValue = cp;
@@ -481,6 +471,30 @@ function Milli_Chart(settings) {
481
471
  _this.scaleinfoY.lowValue -= 1;
482
472
  _this.scaleinfoY.highValue += 1;
483
473
  }
474
+ // do we have any analyzis we need to take into account
475
+
476
+ for (const [key, a] of m_analyzisMethod.entries()) {
477
+ var data;
478
+ if (_this.scaleinfoY.type == 'history') data = a.history;
479
+ else data = a.trades;
480
+ for (var i = 0; i < data.length; i++) {
481
+ if (data[i].timestamp < _this.scaleinfoX.startTimeStamp) {
482
+ continue;
483
+ }
484
+ if (data[i].timestamp > _this.scaleinfoX.endTimeStamp) {
485
+ break;
486
+ }
487
+ if (typeof data[i].datapoints !== 'undefined') {
488
+ for (var x = 0; x < data[i].datapoints.length; x++) {
489
+ if (data[i].datapoints[x] < _this.scaleinfoY.lowValue) _this.scaleinfoY.lowValue = data[i].datapoints[x];
490
+ else
491
+ if (data[i].datapoints[x] > _this.scaleinfoY.highValue) _this.scaleinfoY.highValue = data[i].datapoints[x];
492
+ }
493
+ }
494
+ if (data[i].price < _this.scaleinfoY.lowValue) _this.scaleinfoY.lowValue = data[i].price;
495
+ if (data[i].price > _this.scaleinfoY.highValue) _this.scaleinfoY.highValue = data[i].price;
496
+ }
497
+ }
484
498
  return 1;
485
499
  }
486
500
 
@@ -800,7 +814,6 @@ function Milli_Chart(settings) {
800
814
  _this.scaleinfoX.days = getNumberOfDays(starttime, endtime);
801
815
  _this.scaleinfoX.lineLength = m_chartspaces.chart.right - m_chartspaces.chart.left;
802
816
  var datesize = new Date('2888-12-28'); // bredaste datum jag kan komma på
803
- //_this.scaleinfoX.itemwidth = getStringWidth(m_ctx, '88:88') * 2; // kolla rätt format en 8a för varje tecken
804
817
  _this.scaleinfoX.itemwidth = getStringWidth(m_ctx, formatDate(datesize, _this.settings.dateformat)) * 2; // kolla rätt format en 8a för varje tecken
805
818
 
806
819
  var maxLegendItems = _this.scaleinfoX.lineLength / (_this.scaleinfoX.itemwidth * 2);
@@ -875,7 +888,6 @@ function Milli_Chart(settings) {
875
888
  }
876
889
  }
877
890
  if (draw) {
878
- //drawXAxisGridlines({ 'x': x, y: m_canvas.height - m_chartCss.marginBottom });
879
891
  drawXAxisGridlines({ 'x': x, y: m_chartspaces.chart.height - m_chartCss.marginBottom });
880
892
  text = year;
881
893
  if (_this.scaleinfoX.lineLength + m_chartspaces.chart.left > x - m_ctx.measureText(text).width) { // not to far right?
@@ -883,13 +895,12 @@ function Milli_Chart(settings) {
883
895
  m_ctx.save(); // flip and write new years on top
884
896
  var fontMetrix = m_ctx.measureText(text);
885
897
  x = x + fontMetrix.actualBoundingBoxAscent + fontMetrix.actualBoundingBoxDescent + 2;
886
- var y = m_chartspaces.chart.top; // + m_ctx.measureText(datum).width;
898
+ var y = m_chartspaces.chart.top;
887
899
  m_ctx.translate(x, y);
888
900
  m_ctx.rotate(90 * Math.PI / 180);
889
901
  m_ctx.fillText(text, 0, 0);
890
902
  m_ctx.restore();
891
903
  } else {
892
- //m_ctx.fillText(text, x - (m_ctx.measureText(text).width / 2), m_canvas.height - m_chartCss.marginBottom + 10);
893
904
  m_ctx.fillText(text, x - (m_ctx.measureText(text).width / 2), m_chartspaces.chart.height - m_chartCss.marginBottom + 10);
894
905
  }
895
906
  }
@@ -908,7 +919,6 @@ function Milli_Chart(settings) {
908
919
  x = getXPosition(new Date(year.getFullYear() + '-07-01T00:00:00Z')); // 7
909
920
  draw = true;
910
921
  for (i = 0; i < legendItems.length; i++) {
911
- //if (Math.abs(legendItems[i].x - x) < (getMaxDateWidth() / 2)) {
912
922
  if (Math.abs(legendItems[i].x - x) < getMaxDateWidth()) {
913
923
  draw = false;
914
924
  }
@@ -1076,7 +1086,6 @@ function Milli_Chart(settings) {
1076
1086
  else {
1077
1087
  if (numticks < 2) numticks = 2;
1078
1088
  x = _this.scaleinfoX.milliPerDay / numticks / 60000;
1079
- //x = totalmilli / numticks / 60000;
1080
1089
  if (totalmilli > 4 * 3600000) factor = 60; // 4 timmar
1081
1090
  else
1082
1091
  if (totalmilli > 2 * 3600000) factor = 30; // 2 timmar
@@ -1438,8 +1447,9 @@ function Milli_Chart(settings) {
1438
1447
  return;
1439
1448
  }
1440
1449
  var highy = -1;
1441
- var lowy = m_chartspaces.height;
1442
- for (var x = 0; x < _this.instruments.length; x++) {
1450
+ var lowy = m_chartspaces.chart.height;
1451
+ var toolArray = [];
1452
+ for (x = 0; x < _this.instruments.length; x++) {
1443
1453
  if (_this.instruments[x].insref != 0 && typeof obj.instruments[x] !== 'undefined') {
1444
1454
  var instr = {};
1445
1455
  instr.chartType = _this.scaleinfoY.type;
@@ -1475,16 +1485,6 @@ function Milli_Chart(settings) {
1475
1485
  var pointerHeight = _this.instruments[x].toolTipPointer.offsetHeight + parseInt(pointerStyle.marginTop) + parseInt(pointerStyle.marginBottom);
1476
1486
  _this.instruments[x].toolTip.innerHTML = ttip;
1477
1487
  var posy = obj.instruments[x].y - (_this.instruments[x].toolTip.offsetHeight / 2);
1478
- var tmp = Math.abs(posy - parseFloat(highy));
1479
- var height = _this.instruments[x].toolTip.offsetHeight;
1480
- if (tmp < height) {
1481
- posy = parseFloat(highy) + height;
1482
- }
1483
- tmp = Math.abs(posy - parseFloat(lowy));
1484
- if (tmp < 30) {
1485
- // hur gör vi här? behövs det när vi sätter dom i ordning?
1486
- //posy = parseFloat(highy) + 20;
1487
- }
1488
1488
  if (m_dataPoints.arr[i] + (_this.instruments[x].toolTip.offsetWidth * 1.5) > m_canvas.width || m_dataPoints.arr[i] + (_this.instruments[x].toolTip.offsetWidth * 1.5) > m_canvas.width) { // TODO +10 should be calculated better
1489
1489
  // draw the hover to the left
1490
1490
  _this.instruments[x].toolTip.style.left = (m_dataPoints.arr[i] - _this.instruments[x].toolTip.offsetWidth - (pointerWidth / 2)) + 1 + 'px';
@@ -1493,14 +1493,33 @@ function Milli_Chart(settings) {
1493
1493
  _this.instruments[x].toolTip.style.left = (obj.instruments[x].x + (pointerWidth / 2)) + 'px';
1494
1494
  }
1495
1495
  _this.instruments[x].toolTip.style.top = posy + 'px';
1496
-
1496
+ toolArray.push({ top: (obj.instruments[x].y - (pointerHeight / 2)), instrument: x });
1497
1497
  _this.instruments[x].toolTipPointer.style.left = (obj.instruments[x].x - (pointerWidth / 2)) + 1 + 'px'; // hmm plus 1??
1498
1498
  _this.instruments[x].toolTipPointer.style.top = (obj.instruments[x].y - (pointerHeight / 2)) + 'px';
1499
1499
  if (posy > highy) highy = posy;
1500
1500
  if (posy < lowy) lowy = posy;
1501
1501
 
1502
+ } else {
1503
+ if (_this.instruments[x].toolTip) {
1504
+ _this.instruments[x].toolTip.parentNode.removeChild(_this.instruments[x].toolTip);
1505
+ _this.instruments[x].toolTipPointer.parentNode.removeChild(_this.instruments[x].toolTipPointer);
1506
+ _this.instruments[x].toolTip = undefined;
1507
+ _this.instruments[x].toolTipPointer = undefined;
1508
+ }
1502
1509
  }
1503
1510
  }
1511
+ toolArray.sort((a, b) => a.top - b.top);
1512
+ var lastTop = 0;
1513
+ for (x = 0; x < toolArray.length; x++) {
1514
+ if (x != 0) {
1515
+ //console.log(lastTop,_this.instruments[x-1].toolTip.offsetHeight , toolArray[x].top);
1516
+ if (lastTop + _this.instruments[x - 1].toolTip.offsetHeight > toolArray[x].top) {
1517
+ toolArray[x].top = lastTop + _this.instruments[x - 1].toolTip.offsetHeight;
1518
+ }
1519
+ }
1520
+ _this.instruments[toolArray[x].instrument].toolTip.style.top = toolArray[x].top + 'px';
1521
+ lastTop = toolArray[x].top;
1522
+ }
1504
1523
  return;
1505
1524
  }
1506
1525
 
@@ -1595,6 +1614,31 @@ function Milli_Chart(settings) {
1595
1614
  if (m_zoom.div) m_canvas.parentNode.removeChild(m_zoom.div);
1596
1615
  m_zoom.div = null;
1597
1616
  m_zoom.isZooming = false;
1617
+ for (const [key, a] of m_analyzisMethod.entries()) {
1618
+ switch (a.method) {
1619
+ case 'sma':
1620
+ {
1621
+ a.history = simpleMovingAverage(_this.instruments[0].history, a.length);
1622
+ a.trades = simpleMovingAverage(_this.instruments[0].trades, a.length);
1623
+ }
1624
+ break;
1625
+ case 'ema':
1626
+ {
1627
+ a.history = exponentialMovingAverage(_this.instruments[0].history, a.length);
1628
+ a.trades = exponentialMovingAverage(_this.instruments[0].trades, a.length);
1629
+ break;
1630
+ }
1631
+ case 'bollinger':
1632
+ {
1633
+ a.history = bollingerBands(_this.instruments[0].history, a.length, a.stddev | 2);
1634
+ a = bollingerBands(_this.instruments[0].trades, a.length, a.stddev | 2);
1635
+ break;
1636
+ }
1637
+ default:
1638
+ break;
1639
+ }
1640
+ }
1641
+
1598
1642
  }
1599
1643
  m_lastDrawnInstrument = _this.instruments[0].insref;
1600
1644
  if (m_ctx == null) return;
@@ -1685,6 +1729,12 @@ function Milli_Chart(settings) {
1685
1729
  if (_this.instruments[i].insref != 0)
1686
1730
  plotData(_this.instruments[i].trades, i);
1687
1731
  }
1732
+
1733
+ for (const [key, a] of m_analyzisMethod.entries()) {
1734
+ if (a.method == 'bollinger') plotBollingerBand(a, 'trades');
1735
+ else plotMovingAverage(a, 'trades');
1736
+ }
1737
+
1688
1738
  } else
1689
1739
  if (period == 'm') {
1690
1740
  if (m_zoom.mousedown.timestamp) {
@@ -1692,10 +1742,12 @@ function Milli_Chart(settings) {
1692
1742
  _this.scaleinfoX.endTimeStamp = m_zoom.mousedown.timestamp > m_zoom.mouseup.timestamp ? m_zoom.mousedown.timestamp : m_zoom.mouseup.timestamp;
1693
1743
  _this.scaleinfoX.endTimeStamp -= (_this.scaleinfoX.endTimeStamp % 3600000);
1694
1744
  } else {
1745
+ var startdate = new Date().getTime() - (86400000 * 365 * (isNaN(len) ? 1 : len));
1746
+
1695
1747
  _this.scaleinfoX.startTimeStamp = subtractMonth(new Date(), len);
1696
1748
  _this.scaleinfoX.startTimeStamp = new Date(_this.scaleinfoX.startTimeStamp.toISOString().substring(0, 10) + 'T' + '00:00:00Z').getTime();
1697
1749
  _this.scaleinfoX.startTimeStamp = findFirstWeekDay(_this.scaleinfoX.startTimeStamp).getTime();
1698
- if (_this.instruments[0].history.len > 1 && _this.scaleinfoX.startTimeStamp < _this.instruments[0].history[0].timestamp) _this.scaleinfoX.startTimeStamp = _this.instruments[0].history[0].timestamp;
1750
+ if (_this.instruments[0].history.length > 1 && _this.scaleinfoX.startTimeStamp < _this.instruments[0].history[0].timestamp) _this.scaleinfoX.startTimeStamp = _this.instruments[0].history[0].timestamp;
1699
1751
  _this.scaleinfoX.endTimeStamp = new Date();
1700
1752
  _this.scaleinfoX.endTimeStamp = new Date(_this.scaleinfoX.endTimeStamp.toISOString().substring(0, 10) + 'T' + '00:00:00Z').getTime();
1701
1753
  }
@@ -1712,25 +1764,30 @@ function Milli_Chart(settings) {
1712
1764
  if (_this.instruments[i].insref != 0)
1713
1765
  plotData(_this.instruments[i].history, i);
1714
1766
  }
1767
+ for (const [key, a] of m_analyzisMethod.entries()) {
1768
+ if (a.method == 'bollinger') plotBollingerBand(a, 'history');
1769
+ else plotMovingAverage(a, 'history');
1770
+ }
1715
1771
  } else
1716
- if ((period == 'y' || _this.settings.chartlen == 'ytd' || _this.settings.chartlen == 'max')) { // && _this.instruments[0].history.length != 0) {
1772
+ if ((period == 'y' || _this.settings.chartlen == 'ytd' || _this.settings.chartlen == 'max')) {
1717
1773
  if (m_zoom.mousedown.timestamp) {
1718
1774
  _this.scaleinfoX.startTimeStamp = m_zoom.mousedown.timestamp > m_zoom.mouseup.timestamp ? m_zoom.mouseup.timestamp : m_zoom.mousedown.timestamp;
1719
1775
  _this.scaleinfoX.startTimeStamp -= (_this.scaleinfoX.startTimeStamp % 3600000);
1720
1776
  _this.scaleinfoX.endTimeStamp = m_zoom.mousedown.timestamp > m_zoom.mouseup.timestamp ? m_zoom.mousedown.timestamp : m_zoom.mouseup.timestamp;
1721
1777
  _this.scaleinfoX.endTimeStamp -= (_this.scaleinfoX.endTimeStamp % 3600000);
1722
1778
  } else {
1723
- var startdate;
1779
+ var startdateM;
1724
1780
  if (_this.settings.chartlen == 'max' && _this.instruments[0].history.length > 1) {
1725
- startdate = _this.instruments[0].history[0].timestamp;
1781
+ startdateM = _this.instruments[0].history[0].timestamp;
1726
1782
  } else
1727
1783
  if (_this.settings.chartlen == 'ytd') {
1728
- startdate = new Date(new Date().getFullYear() - 1 + '-12-30').getTime(); // TODO, hur skall vi göra här om det inte finns data runt här?
1784
+ //startdateM = new Date(new Date().getFullYear() - 1 + '-12-30').getTime(); // TODO, hur skall vi göra här om det inte finns data runt här?
1785
+ startdateM = new Date(new Date().getFullYear() + '-01-01').getTime(); // TODO, hur skall vi göra här om det inte finns data runt här?
1729
1786
  } else {
1730
- startdate = new Date().getTime() - (86400000 * 365 * (isNaN(len) ? 1 : len));
1787
+ startdateM = new Date().getTime() - (86400000 * 365 * (isNaN(len) ? 1 : len));
1731
1788
  }
1732
- if (_this.instruments[0].history.length > 1 && startdate < _this.instruments[0].history[0].timestamp) startdate = _this.instruments[0].history[0].timestamp;
1733
- _this.scaleinfoX.startTimeStamp = startdate;
1789
+ if (_this.instruments[0].history.length > 1 && startdateM < _this.instruments[0].history[0].timestamp) startdateM = _this.instruments[0].history[0].timestamp;
1790
+ _this.scaleinfoX.startTimeStamp = startdateM;
1734
1791
  _this.scaleinfoX.startTimeStamp = findFirstWeekDay(_this.scaleinfoX.startTimeStamp).getTime();
1735
1792
  _this.scaleinfoX.endTimeStamp = new Date();
1736
1793
  _this.scaleinfoX.endTimeStamp = new Date(_this.scaleinfoX.endTimeStamp.toISOString().substring(0, 10) + 'T' + '00:00:00Z').getTime();
@@ -1748,6 +1805,12 @@ function Milli_Chart(settings) {
1748
1805
  if (_this.instruments[i].insref != 0)
1749
1806
  plotData(_this.instruments[i].history, i);
1750
1807
 
1808
+ for (const [key, a] of m_analyzisMethod.entries()) {
1809
+ if (a.method == 'bollinger') plotBollingerBand(a, 'history');
1810
+ else plotMovingAverage(a, 'history');
1811
+ }
1812
+
1813
+
1751
1814
  }
1752
1815
  drawBoxShadow(m_chartspaces.chart);
1753
1816
  if (m_chartspaces.chart.percent != 100) {
@@ -1919,6 +1982,7 @@ function Milli_Chart(settings) {
1919
1982
  };
1920
1983
 
1921
1984
  function plotExternalHistoricalData(data) {
1985
+ // används för dividend osv
1922
1986
  m_ctx.save();
1923
1987
  var startpoint = { x: 0, y: 0 };
1924
1988
  var endpoint = { x: 0, y: 0 };
@@ -1976,6 +2040,133 @@ function Milli_Chart(settings) {
1976
2040
  m_ctx.restore();
1977
2041
  }
1978
2042
 
2043
+ function calcAnalyzisLine(data, pricecol) {
2044
+ var startpoint = { x: 0, y: 0 };
2045
+ var endpoint = { x: 0, y: 0 };
2046
+ var startDate = _this.scaleinfoX.startTimeStamp;
2047
+ var len = data.length;
2048
+ var lastdate = new Date(_this.scaleinfoX.startTimeStamp);
2049
+ var offset = 0;
2050
+ var maxy = 0;
2051
+ var ret = [];
2052
+ for (var i = 0; i < len; i++) {
2053
+ var currentDate;
2054
+ var tmpx = startpoint.x;
2055
+ var tmp;
2056
+ if (data[i].timestamp < _this.scaleinfoX.startTimeStamp) {
2057
+ continue;
2058
+ }
2059
+ if (data[i].timestamp > _this.scaleinfoX.endTimeStamp) {
2060
+ break;
2061
+ }
2062
+
2063
+ if (_this.scaleinfoY.type != 'history' && (data[i].timestamp % 86400000 < _this.instruments[0].opentimestamp || data[i].timestamp % 86400000 > _this.instruments[0].closetimestamp)) {
2064
+ continue;
2065
+ }
2066
+ var endtimeToday = new Date(data[i].timestamp);
2067
+ if (endtimeToday.getDay() == 0 || endtimeToday.getDay() == 6) continue;
2068
+ if (_this.scaleinfoY.type != 'history') {
2069
+ endtimeToday = new Date(endtimeToday.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketclose + 'Z'); // borde räcka att göra 1 gång när det blir nytt datum
2070
+ }
2071
+ if (data[i].timestamp > endtimeToday.getTime()) {
2072
+ continue; // dataticks efter stängning ritas inte
2073
+ }
2074
+ currentDate = new Date(data[i].timestamp);
2075
+ currentDate.setHours(lastdate.getHours());
2076
+ currentDate.setMinutes(lastdate.getMinutes());
2077
+ currentDate.setSeconds(lastdate.getSeconds());
2078
+ if (lastdate.toISOString().substring(0, 10) != currentDate.toISOString().substring(0, 10)) { // new date
2079
+ tmp = new Date(lastdate.toISOString().substring(0, 10) + 'T' + _this.instruments[0].marketclose + 'Z');
2080
+ var nextDate = new Date(data[i].timestamp);
2081
+ tmp = tmp.getTime() + 86400000 - _this.scaleinfoX.milliPerDay; // increase to next days starttime
2082
+
2083
+ currentDate = new Date(tmp);
2084
+ while (dateDiffInDays(currentDate, nextDate) > 0) {
2085
+ if (currentDate.getDay() == 0 || currentDate.getDay() == 6)
2086
+ offset += 86400000 / _this.scaleinfoX.timePerPixel;
2087
+ else
2088
+ offset += ((86400000 - _this.scaleinfoX.milliPerDay) / _this.scaleinfoX.timePerPixel);
2089
+ currentDate = new Date(currentDate.getTime() + 86400000);
2090
+ }
2091
+ offset += ((86400000 - _this.scaleinfoX.milliPerDay) / _this.scaleinfoX.timePerPixel); // * dateDiffInDays(lastdate, currentDate);
2092
+ lastdate = currentDate;
2093
+ startpoint.x = Math.round(m_chartspaces.chart.left + ((data[i].timestamp - startDate) / _this.scaleinfoX.timePerPixel)) + 0.5 - offset;
2094
+
2095
+ // TODO: här blir det fel när det är från 00:00: 23:59 men göms av tmpx < startpoint.x
2096
+ if (_this.scaleinfoY.type == 'trades' && tmpx < startpoint.x) {
2097
+ ret.push(startpoint.x, startpoint.y);
2098
+ }
2099
+ }
2100
+ startpoint.y = Math.round(m_chartspaces.chart.height - m_chartCss.marginBottom - ((data[i].datapoints[pricecol] - _this.scaleinfoY.minValue) * _this.scaleinfoY.valuePerPixel)) + 0.5;
2101
+ maxy = maxy > startpoint.y ? maxy : startpoint.y;
2102
+
2103
+ startpoint.x = Math.round(m_chartspaces.chart.left + ((data[i].timestamp - _this.scaleinfoX.startDate.getTime()) / _this.scaleinfoX.timePerPixel)) + 0.5;
2104
+ startpoint.x -= offset;
2105
+
2106
+ if (startpoint.x != endpoint.x || startpoint.y != endpoint.y) {
2107
+ var x = Math.round(startpoint.x);
2108
+ if (endpoint.x != 0) {
2109
+ if (tmpx < startpoint.x) {
2110
+ if (_this.settings.hcurve) m_ctx.lineTo(startpoint.x, endpoint.y);
2111
+ ret.push({ x: startpoint.x, y: startpoint.y });
2112
+ }
2113
+ } else {
2114
+ ret.push({ x: startpoint.x, y: startpoint.y });
2115
+ }
2116
+ endpoint.x = startpoint.x;
2117
+ endpoint.y = startpoint.y;
2118
+ }
2119
+ }
2120
+ return ret;
2121
+ }
2122
+
2123
+ function plotMovingAverage(method, type) {
2124
+ var data = method[type];
2125
+ m_ctx.strokeStyle = method.color;
2126
+ m_ctx.lineWidth = method.lineWidth | 1;
2127
+ var line = calcAnalyzisLine(data, 0);
2128
+ if (line.length == 0) return;
2129
+ m_ctx.save();
2130
+ m_ctx.beginPath();
2131
+ m_ctx.closePath(); // clear path
2132
+ m_ctx.moveTo(line[0].x, line[0].y);
2133
+ for (var i = 1; i < line.length; i++) {
2134
+ m_ctx.lineTo(line[i].x, line[i].y);
2135
+ }
2136
+ m_ctx.stroke();
2137
+ m_ctx.restore();
2138
+ }
2139
+
2140
+ function plotBollingerBand(method, type) {
2141
+ var data = method[type];
2142
+ var upper = calcAnalyzisLine(data, 0, null);
2143
+ var lower = calcAnalyzisLine(data, 1, null);
2144
+ if (upper.length == 0 || lower.length == 0) return;
2145
+ m_ctx.strokeStyle = method.color;
2146
+ m_ctx.lineWidth = method.lineWidth | 1;
2147
+ m_ctx.save();
2148
+ m_ctx.beginPath();
2149
+ var upper = calcAnalyzisLine(data, 0, null);
2150
+ var lower = calcAnalyzisLine(data, 1, null);
2151
+ for (var i = 0; i < upper.length; i++) m_ctx.lineTo(upper[i].x, upper[i].y);
2152
+ m_ctx.lineTo(lower[lower.length - 1].x, lower[lower.length - 1].y);
2153
+ for (var i = lower.length - 1; i >= 0; i--) m_ctx.lineTo(lower[i].x, lower[i].y);
2154
+ if (method.border) m_ctx.stroke();
2155
+ m_ctx.closePath();
2156
+ if (method.fill) {
2157
+ m_ctx.fillStyle = method.fill;
2158
+ m_ctx.fill();
2159
+ }
2160
+ var sma = calcAnalyzisLine(data, 2);
2161
+ m_ctx.beginPath();
2162
+ m_ctx.closePath(); // clear path
2163
+ m_ctx.moveTo(sma[0].x, sma[0].y);
2164
+ for (var i = 0; i < sma.length; i++) m_ctx.lineTo(sma[i].x, sma[i].y);
2165
+ m_ctx.stroke();
2166
+ m_ctx.restore();
2167
+ return;
2168
+ }
2169
+
1979
2170
  function plotData(data, instrument) {
1980
2171
  m_ctx.save();
1981
2172
  m_ctx.strokeStyle = m_instrumentCss[instrument].color;
@@ -2061,17 +2252,13 @@ function Milli_Chart(settings) {
2061
2252
  }
2062
2253
  offset += ((86400000 - _this.scaleinfoX.milliPerDay) / _this.scaleinfoX.timePerPixel); // * dateDiffInDays(lastdate, currentDate);
2063
2254
  lastdate = currentDate;
2064
- //console.log(startpoint.x);
2065
2255
  startpoint.x = Math.round(m_chartspaces.chart.left + ((data[i].timestamp - startDate) / _this.scaleinfoX.timePerPixel)) + 0.5 - offset;
2066
- //console.log(startpoint.x);
2067
2256
 
2068
2257
  // TODO: här blir det fel när det är från 00:00: 23:59 men göms av tmpx < startpoint.x
2069
2258
  if (_this.scaleinfoY.type == 'trades' && tmpx < startpoint.x) {
2070
2259
  m_ctx.lineTo(startpoint.x, startpoint.y);
2071
2260
  }
2072
- //m_ctx.lineTo(startpoint.x, startpoint.y);
2073
2261
  }
2074
- //startpoint.y = Math.round(m_canvas.height - m_chartCss.marginBottom - (((data[i].price * factor) - _this.scaleinfoY.minValue) * _this.scaleinfoY.valuePerPixel)) + 0.5;
2075
2262
  startpoint.y = Math.round(m_chartspaces.chart.height - m_chartCss.marginBottom - (((data[i].price * factor) - _this.scaleinfoY.minValue) * _this.scaleinfoY.valuePerPixel)) + 0.5;
2076
2263
  maxy = maxy > startpoint.y ? maxy : startpoint.y;
2077
2264
 
@@ -2180,6 +2367,116 @@ function Milli_Chart(settings) {
2180
2367
  m_zoom.mouseup.timestamp = null;
2181
2368
  };
2182
2369
 
2370
+ function bollingerBands(prices, window, stddev) {
2371
+ if (!prices || prices.length < window) {
2372
+ return [];
2373
+ }
2374
+
2375
+ let index = window - 1;
2376
+ const length = prices.length + 1;
2377
+ const standardDeviations = [];
2378
+ while (++index < length) {
2379
+ const windowSlice = prices.slice(index - window, index);
2380
+ const mean = windowSlice.reduce((prev, curr) => prev + curr.price, 0) / window;
2381
+ const variance = Math.sqrt(windowSlice.reduce((a, b) => a + (b.price - mean) ** 2, 0) / window) * stddev;
2382
+ const uppervariance = mean + variance;
2383
+ const lowervariance = mean - variance;
2384
+ standardDeviations.push({ timestamp: prices[index - 1].timestamp, datapoints: [uppervariance, lowervariance, mean] });
2385
+ }
2386
+ return standardDeviations;
2387
+ }
2388
+
2389
+ function simpleMovingAverage(prices, window, n = Infinity) {
2390
+ if (!prices || prices.length < window) {
2391
+ return [];
2392
+ }
2393
+
2394
+ let index = window - 1;
2395
+ const length = prices.length + 1;
2396
+
2397
+ const simpleMovingAverages = [];
2398
+
2399
+ let numberOfSMAsCalculated = 0;
2400
+
2401
+ while (++index < length && numberOfSMAsCalculated++ < n) {
2402
+ const windowSlice = prices.slice(index - window, index);
2403
+ const sum = windowSlice.reduce((prev, curr) => prev + curr.price, 0);
2404
+ simpleMovingAverages.push({ timestamp: prices[index - 1].timestamp, datapoints: [sum / window] });
2405
+ }
2406
+ return simpleMovingAverages;
2407
+ }
2408
+
2409
+ function exponentialMovingAverage(prices, window) {
2410
+ if (!prices || prices.length < window) {
2411
+ return [];
2412
+ }
2413
+ let index = window - 1;
2414
+ let previousEmaIndex = 0;
2415
+ const length = prices.length;
2416
+ const smoothingFactor = 2 / (window + 1);
2417
+ const exponentialMovingAverages = [];
2418
+
2419
+ const [sma] = simpleMovingAverage(prices, window, 1);
2420
+ exponentialMovingAverages.push(sma);
2421
+ while (++index < length) {
2422
+ const value = prices[index].price;
2423
+ const previousEma = [exponentialMovingAverages[previousEmaIndex++].datapoints[0]];
2424
+ const currentEma = (value * smoothingFactor) + (previousEma * (1 - smoothingFactor));
2425
+ exponentialMovingAverages.push({ timestamp: prices[index].timestamp, datapoints: [currentEma] });
2426
+ }
2427
+ return exponentialMovingAverages;
2428
+ }
2429
+ _this.removeIndicator = function(index) {
2430
+ if (m_analyzisMethod.get(index)) {
2431
+ m_analyzisMethod.delete(index);
2432
+ _this.drawChart();
2433
+ return true;
2434
+ }
2435
+ return false;
2436
+ }
2437
+
2438
+ _this.addIndicator = function(method) {
2439
+ if (typeof method !== 'object' || method == null || typeof method.type == undefined) return;
2440
+ switch (method.method) {
2441
+ case 'sma':
2442
+ {
2443
+ if (typeof method.length === undefined) return;
2444
+ method.history = simpleMovingAverage(_this.instruments[0].history, method.length);
2445
+ method.trades = simpleMovingAverage(_this.instruments[0].trades, method.length);
2446
+ }
2447
+ break;
2448
+ case 'ema':
2449
+ {
2450
+ if (typeof method.length === undefined) return;
2451
+ method.index = m_analyzisIndex++;
2452
+ method.history = exponentialMovingAverage(_this.instruments[0].history, method.length);
2453
+ method.trades = exponentialMovingAverage(_this.instruments[0].trades, method.length);
2454
+ break;
2455
+ }
2456
+ case 'bollinger':
2457
+ {
2458
+ if (typeof method.length === undefined) return;
2459
+ if (!method.stddev) method.stddev = 2;
2460
+ if (!method.length) method.stddev = 20;
2461
+ method.index = m_analyzisIndex++;
2462
+ method.history = bollingerBands(_this.instruments[0].history, method.length, method.stddev | 2);
2463
+ method.trades = bollingerBands(_this.instruments[0].trades, method.length, method.stddev | 2);
2464
+ break;
2465
+ }
2466
+ default:
2467
+ if (typeof method.history !== 'undefined' && typeof method.trades !== 'undefined') {
2468
+ if (!Array.isArray(method.history) || !Array.isArray(method.trades)) {
2469
+ return -1;
2470
+ }
2471
+ }
2472
+ break;
2473
+ }
2474
+ method.index = m_analyzisIndex++;
2475
+ m_analyzisMethod.set(method.index, method);
2476
+ console.log(method, m_analyzisMethod);
2477
+ _this.drawChart();
2478
+ };
2479
+
2183
2480
  _this.removeAllCompares = function() {
2184
2481
  if (_this.instruments.length == 1) return;
2185
2482
  for (var i = 0; i < 3; i++)
@@ -2191,7 +2488,6 @@ function Milli_Chart(settings) {
2191
2488
  if (instrument == 0 || isNaN(instrument)) return;
2192
2489
  for (var i = 0; i < _this.instruments.length; i++) {
2193
2490
  if (_this.instruments[i].insref == instrument) {
2194
- // _this.instruments.splice(i, 1);
2195
2491
  _this.instruments[i] = { insref: 0 };
2196
2492
  _this.drawChart();
2197
2493
  }
@@ -2209,7 +2505,6 @@ function Milli_Chart(settings) {
2209
2505
  if (_this.instruments[pos].insref == 0) break;
2210
2506
  }
2211
2507
  if (pos == 4) return 0;
2212
- // if (_this.instruments.length > 3) return; // MAX 4 instruments (3 compares)
2213
2508
  var instrument = parseInt(insref);
2214
2509
  if (instrument == 0 || isNaN(instrument)) return 0;
2215
2510
  for (i = 0; i < _this.instruments.length; i++) {
@@ -2226,12 +2521,17 @@ function Milli_Chart(settings) {
2226
2521
  };
2227
2522
 
2228
2523
  _this.instruments[pos] = instr;
2524
+ var oldfields = _this.settings.fields;
2229
2525
  if (_this.settings.compare1 != '') {
2230
- var url = milli_data_api_url + "widget=intradaychart&token=" + _this.settings.token + "&target=buildwidget&fields=name,tradecurrency,date,time,tradeprice,tradequantity,marketopen,marketclose&language=sv&compress=1&insref=" + instrument + '&intradaylen=' + _this.settings.intradaylen;
2526
+ _this.settings.fields = [...['name', 'tradecurrency', 'time', 'date', 'tradeprice', 'tradequantity', 'marketopen', 'marketclose', 'closeprice1d'], ...oldfields];
2527
+ var url = milli_data_api_url + "widget=intradaychart&token=" + _this.settings.token + "&target=buildwidget&fields=" + _this.settings.fields + "&language=sv&compress=1&insref=" + instrument + '&intradaylen=' + _this.settings.intradaylen;
2528
+ _this.settings.fields = oldfields;
2231
2529
  millistream_data_api.fetch(url, function(data) {
2232
2530
  drawCompare(data);
2233
2531
  });
2234
- url = milli_data_api_url + "widget=historychart&token=" + _this.settings.token + "&target=buildwidget&insref=" + instrument + "&fields=name,tradecurrency,date,closeprice,closequantity,marketopen,marketclose&language=sv&startdate=" + _this.settings.startdate + "&adjusted=1";
2532
+ _this.settings.fields = [...['name', 'tradecurrency', 'date', 'closeprice', 'closequantity', 'marketopen', 'marketclose'], ...oldfields];
2533
+ url = milli_data_api_url + "widget=historychart&token=" + _this.settings.token + "&target=buildwidget&insref=" + instrument + "&fields=" + _this.settings.fields + "&language=sv&startdate=" + _this.settings.startdate + "&adjusted=1";
2534
+ _this.settings.fields = oldfields;
2235
2535
  millistream_data_api.fetch(url, function(data) {
2236
2536
  drawCompare(data);
2237
2537
  });
@@ -2255,11 +2555,9 @@ function Milli_Chart(settings) {
2255
2555
  var period = _this.settings.chartlen.substring(_this.settings.chartlen.length - 1);
2256
2556
  var len = parseInt(_this.settings.chartlen.substring(0, _this.settings.chartlen.length - 1));
2257
2557
  if ((period == 'd' && _this.settings.chartlen != 'ytd') && typeof resp[0].trades === 'undefined') {
2258
- //console.log('typeof resp.trades', typeof resp[0].trades, period, _this.settings.chartlen);
2259
2558
  return;
2260
2559
  }
2261
2560
  if ((period == 'm' || period == 'y' || _this.settings.chartlen == 'ytd' || _this.settings.chartlen == 'max') && typeof resp[0].history === 'undefined') {
2262
- //console.log('typeof resp.history', typeof resp[0].history, resp);
2263
2561
  return;
2264
2562
  }
2265
2563
 
@@ -2324,17 +2622,14 @@ function Milli_Chart(settings) {
2324
2622
  _this.drawChart();
2325
2623
 
2326
2624
  if (_this.settings.streaming != false && typeof resp[0].trades !== 'undefined') {
2327
- /*if (MillistreamWidgetApi_isObjectEmpty(_this.unsubscriptions) == false) {
2328
- _this.settings.streaming.MillistreamWidgetStreamingApi_unsubscribe(_this);
2329
- }*/
2330
2625
  m_requestid = _this.settings.streaming.MillistreamWidgetStreamingApi_subscribeInstruments(_this, m_requestid, [_this.settings.instrument]);
2331
- //_this.requestid = _this.settings.streaming.MillistreamWidgetStreamingApi_subscribeInstruments(_this, _this.requestid, m_insrefs);
2332
2626
  }
2333
2627
  if (_this.settings.onreadyCallback) _this.settings.onreadyCallback();
2334
2628
  };
2335
2629
 
2336
2630
  _this.streamingCallback = function(insref, mref, json) {
2337
2631
  var update = false;
2632
+ var calcAnalyizis = false;
2338
2633
  var instr = _this.instruments.find(function(item) {
2339
2634
  return item.insref == insref;
2340
2635
  });
@@ -2344,38 +2639,62 @@ function Milli_Chart(settings) {
2344
2639
  if (json['3'] && json['36'] && json['13'] && (json['12'] || json['201'])) {
2345
2640
  var timestamp = new Date(json['3'] + 'T' + json['36'].substring(0, 6) + '00' + 'Z').getTime();
2346
2641
 
2347
- // TODO hash/strangle with YYYY-mm-dd hh:mm:00 trades and only draw once per minute
2348
2642
  var data = instr.hashmap.get(timestamp);
2349
- if (data != 'undefined') {
2643
+ if (typeof data === 'undefined') {
2350
2644
  update = true;
2351
2645
  data = {};
2352
2646
  //data.tradereference = json['14'];
2353
2647
  data.timestamp = timestamp;
2354
2648
  instr.hashmap.set(data.timestamp, data);
2649
+ calcAnalyizis = true;
2355
2650
  data.price = parseFloat(json['12']); // eller 201 för tradeyield
2356
2651
  data.open = parseFloat(json['12']); // eller 201 för tradeyield
2357
2652
  data.high = parseFloat(json['12']); // eller 201 för tradeyield
2358
2653
  data.low = parseFloat(json['12']); // eller 201 för tradeyield
2359
2654
  data.quantity = parseInt(json['13']);
2655
+
2360
2656
  if (instr.trades.length != 0 && data.timestamp < instr.trades[instr.trades.length - 1].timestamp) {
2361
2657
  //console.log("pushtrade is older than last trade ignoring, should file it on correct postition");
2362
2658
  } else
2363
2659
  instr.trades.push(data);
2364
2660
  } else {
2661
+ if (data.price != parseFloat(json['12']))
2662
+ calcAnalyizis = true;
2365
2663
  data.price = parseFloat(json['12']); // eller 201 för tradeyield
2366
2664
  data.quantity += parseInt(json['13']);
2367
2665
  update = true;
2368
2666
  // updatera med quantity, open , high,low osv?
2369
2667
  }
2370
2668
  }
2371
- if (update) _this.drawChart(); // hover försvinner... (harris också)
2669
+ if (calcAnalyizis) {
2670
+ for (const [key, a] of m_analyzisMethod.entries()) {
2671
+ switch (a.method) {
2672
+ case 'sma':
2673
+ a.trades = [];
2674
+ a.trades = simpleMovingAverage(_this.instruments[0].trades, a.length);
2675
+ break;
2676
+ case 'ema':
2677
+ a.trades = [];
2678
+ a.trades = exponentialMovingAverage(_this.instruments[0].trades, a.length);
2679
+ break;
2680
+ case 'bollinger':
2681
+ a.trades = [];
2682
+ a.trades = bollingerBands(_this.instruments[0].trades, a.length, a.stddev | 2);
2683
+ break;
2684
+ default:
2685
+ // draw custom added?
2686
+ break;
2687
+ }
2688
+ }
2689
+ }
2690
+
2691
+ if (update && _this.settings.chartlen != 'ytd' && _this.settings.chartlen.substring(_this.settings.chartlen.length - 1) == 'd') { // do not redraw if not tickchart
2692
+ _this.drawChart();
2693
+ }
2372
2694
  };
2373
2695
 
2374
2696
  function changeOrientation() {
2375
2697
  if (m_canvas == null) return;
2376
- // set size 0 so target div does not expand due to chartsize
2377
- //readCss(); // TODO
2378
-
2379
2698
  m_canvas.setAttribute('height', _this.settings.target.getBoundingClientRect().height);
2380
2699
  m_canvas.setAttribute('width', _this.settings.target.getBoundingClientRect().width);
2381
2700
  _this.drawChart();
@@ -2385,15 +2704,22 @@ function Milli_Chart(settings) {
2385
2704
  var req = new XMLHttpRequest();
2386
2705
  req.onload = function() {
2387
2706
  _this.buildwidget(JSON.parse(this.responseText));
2388
- }
2707
+ };
2389
2708
  req.open("GET", url, true);
2390
2709
  req.onerror = function(error) {
2391
2710
  console.log('Fetch data error', error);
2392
- }
2711
+ };
2393
2712
  req.send();
2394
2713
  }
2395
2714
 
2396
- this.drawWidget = function() {
2715
+ _this.destroyWidget = function() {
2716
+ // if we have subscriptions send in an empty array to unsubscribe all and release it
2717
+ if (MillistreamWidgetApi_isObjectEmpty(_this.unsubscriptions) == false)
2718
+ _this.requestid = _this.settings.streaming.MillistreamWidgetStreamingApi_subscribeInstruments(_this, _this.requestid, []);
2719
+ return 0;
2720
+ };
2721
+
2722
+ _this.drawWidget = function() {
2397
2723
  // remove standard fields from array, they will be requested anyway
2398
2724
  _this.settings.fields = _this.settings.fields.filter(function(obj) {
2399
2725
  return ['name', 'tradecurrency', 'time', 'date', 'tradeprice', 'tradequantity', 'marketopen', 'marketclose', 'closeprice1d', 'closeprice', 'closequantity'].indexOf(obj) == -1;
@@ -2405,15 +2731,13 @@ function Milli_Chart(settings) {
2405
2731
  m_dummyDiv.style.display = 'none';
2406
2732
  m_dummyDiv.setAttribute('class', 'millistream-chart');
2407
2733
  _this.settings.target.appendChild(m_dummyDiv);
2408
- _this.instruments = []; // Hmm
2409
- var instr = {
2734
+ _this.instruments[0] = {
2410
2735
  insref: _this.settings.instrument,
2411
2736
  history: [],
2412
2737
  trades: [],
2413
2738
  hashmap: new Map(),
2414
2739
  intradayQuantity: []
2415
2740
  };
2416
- _this.instruments.push(instr);
2417
2741
  var d, url, oldfields;
2418
2742
  if (_this.settings.intradaylen) {
2419
2743
  d = new Date().getTime();
@@ -2431,7 +2755,6 @@ function Milli_Chart(settings) {
2431
2755
  oldfields = _this.settings.fields;
2432
2756
  _this.settings.fields = [...['name', 'tradecurrency', 'time', 'date', 'tradeprice', 'tradequantity', 'marketopen', 'marketclose', 'closeprice1d'], ...oldfields];
2433
2757
  _this.settings.startdate = e.getFullYear() + '-' + zeroPad(e.getMonth() + 1, 2) + '-' + zeroPad(e.getDate(), 2);
2434
- //_this.settings.startdateintraday = _this.settings.startdate;
2435
2758
  url = MillistreamWidgetApi_buildQuery(_this, 'intradaychart');
2436
2759
  _this.settings.fields = oldfields;
2437
2760
  if (_this.settings.xhr) {
@@ -2479,9 +2802,7 @@ function Milli_Chart(settings) {
2479
2802
  startdate -= 86400000 * 365 * len; // remember leapyear
2480
2803
  break;
2481
2804
  case 'x':
2482
- //startdate -= 86400000 * 365 * 10; // remember leapyear
2483
2805
  startdate = new Date('1970-01-01T00:00:00Z').getTime();
2484
- //console.log(startdate);
2485
2806
  break;
2486
2807
  }
2487
2808
  // must be reset when changing from intraday -> history and vice versa
package/package.json CHANGED
@@ -1,11 +1,14 @@
1
1
  {
2
2
  "name": "@millistream/millistream-widgets",
3
- "version": "1.0.0",
3
+ "version": "1.0.3",
4
4
  "description": "Millistream widgets node package",
5
5
  "main": "millistream-widgets.js",
6
6
  "scripts": {
7
7
  "test": "echo \"Error: no test specified\" && exit 1"
8
8
  },
9
9
  "author": "Mats Fors (http://www.millistream.com)",
10
- "license": "GPL-3.0"
10
+ "license": "GPL-3.0",
11
+ "repository": {
12
+ "private": true
13
+ }
11
14
  }