binbot-charts 0.0.4 → 0.0.5
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/dist/TVChartContainer.js +21 -28
- package/dist/datafeed.js +183 -0
- package/dist/helpers.js +47 -0
- package/dist/streaming.js +142 -0
- package/package.json +2 -2
package/dist/TVChartContainer.js
CHANGED
|
@@ -5,45 +5,49 @@ require("core-js/modules/web.dom-collections.iterator.js");
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", {
|
|
6
6
|
value: true
|
|
7
7
|
});
|
|
8
|
-
exports.
|
|
8
|
+
exports.default = void 0;
|
|
9
9
|
|
|
10
|
-
var
|
|
10
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
11
11
|
|
|
12
12
|
var _charting_library = require("../charting_library");
|
|
13
13
|
|
|
14
|
+
var _datafeed = _interopRequireDefault(require("./datafeed"));
|
|
15
|
+
|
|
16
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
17
|
+
|
|
14
18
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
15
19
|
|
|
16
20
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
17
21
|
|
|
18
22
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
19
23
|
|
|
20
|
-
class TVChartContainer extends
|
|
24
|
+
class TVChartContainer extends _react.Component {
|
|
21
25
|
constructor(props) {
|
|
22
26
|
super(props);
|
|
23
27
|
|
|
24
28
|
_defineProperty(this, "tvWidget", null);
|
|
25
29
|
|
|
26
|
-
this.ref = /*#__PURE__*/
|
|
30
|
+
this.ref = /*#__PURE__*/_react.default.createRef();
|
|
27
31
|
}
|
|
28
32
|
|
|
29
33
|
componentDidMount() {
|
|
30
34
|
const widgetOptions = {
|
|
31
35
|
symbol: "AAPL",
|
|
32
36
|
// BEWARE: no trailing slash is expected in feed URL
|
|
33
|
-
datafeed:
|
|
34
|
-
interval: this.props.interval,
|
|
37
|
+
datafeed: _datafeed.default,
|
|
38
|
+
// interval: this.props.interval,
|
|
35
39
|
container: this.ref.current,
|
|
36
40
|
library_path: this.props.libraryPath,
|
|
37
41
|
locale: "en",
|
|
38
|
-
disabled_features: ["use_localstorage_for_settings"],
|
|
39
|
-
enabled_features: ["study_templates"],
|
|
40
|
-
charts_storage_url: this.props.chartsStorageUrl,
|
|
41
|
-
charts_storage_api_version: this.props.chartsStorageApiVersion,
|
|
42
|
-
client_id: this.props.clientId,
|
|
43
|
-
user_id: this.props.userId,
|
|
44
|
-
fullscreen:
|
|
45
|
-
autosize:
|
|
46
|
-
studies_overrides:
|
|
42
|
+
// disabled_features: ["use_localstorage_for_settings"],
|
|
43
|
+
// enabled_features: ["study_templates"],
|
|
44
|
+
// charts_storage_url: this.props.chartsStorageUrl,
|
|
45
|
+
// charts_storage_api_version: this.props.chartsStorageApiVersion,
|
|
46
|
+
// client_id: this.props.clientId,
|
|
47
|
+
// user_id: this.props.userId,
|
|
48
|
+
fullscreen: false,
|
|
49
|
+
autosize: false,
|
|
50
|
+
studies_overrides: {}
|
|
47
51
|
};
|
|
48
52
|
const tvWidget = new _charting_library.widget(widgetOptions);
|
|
49
53
|
this.tvWidget = tvWidget;
|
|
@@ -61,7 +65,7 @@ class TVChartContainer extends React.PureComponent {
|
|
|
61
65
|
}
|
|
62
66
|
|
|
63
67
|
render() {
|
|
64
|
-
return /*#__PURE__*/
|
|
68
|
+
return /*#__PURE__*/_react.default.createElement("div", {
|
|
65
69
|
ref: this.ref,
|
|
66
70
|
style: {
|
|
67
71
|
height: "calc(100vh - 80px)"
|
|
@@ -71,15 +75,4 @@ class TVChartContainer extends React.PureComponent {
|
|
|
71
75
|
|
|
72
76
|
}
|
|
73
77
|
|
|
74
|
-
exports.
|
|
75
|
-
|
|
76
|
-
_defineProperty(TVChartContainer, "defaultProps", {
|
|
77
|
-
symbol: "AAPL",
|
|
78
|
-
interval: "D",
|
|
79
|
-
datafeedUrl: "https://demo_feed.tradingview.com",
|
|
80
|
-
libraryPath: "/charting_library/",
|
|
81
|
-
chartsStorageApiVersion: "1.1",
|
|
82
|
-
fullscreen: false,
|
|
83
|
-
autosize: true,
|
|
84
|
-
studiesOverrides: {}
|
|
85
|
-
});
|
|
78
|
+
exports.default = TVChartContainer;
|
package/dist/datafeed.js
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
require("core-js/modules/web.dom-collections.iterator.js");
|
|
9
|
+
|
|
10
|
+
require("core-js/modules/es.promise.js");
|
|
11
|
+
|
|
12
|
+
require("core-js/modules/es.symbol.description.js");
|
|
13
|
+
|
|
14
|
+
var _helpers = require("./helpers.js");
|
|
15
|
+
|
|
16
|
+
var _streaming = require("./streaming.js");
|
|
17
|
+
|
|
18
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
19
|
+
|
|
20
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
21
|
+
|
|
22
|
+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
23
|
+
|
|
24
|
+
const lastBarsCache = new Map();
|
|
25
|
+
const exchange = "Binance";
|
|
26
|
+
const configurationData = {
|
|
27
|
+
supported_resolutions: ["1D", "1W", "1M"],
|
|
28
|
+
exchanges: [{
|
|
29
|
+
value: "Binance",
|
|
30
|
+
name: "Binance",
|
|
31
|
+
desc: "Binance"
|
|
32
|
+
}],
|
|
33
|
+
symbols_types: [{
|
|
34
|
+
name: "crypto",
|
|
35
|
+
// `symbolType` argument for the `searchSymbols` method, if a user selects this symbol type
|
|
36
|
+
value: "crypto"
|
|
37
|
+
} // ...
|
|
38
|
+
]
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
async function getAllSymbols() {
|
|
42
|
+
const data = await (0, _helpers.makeApiRequest)("data/v3/all/exchanges");
|
|
43
|
+
let allSymbols = [];
|
|
44
|
+
const pairs = data.Data[exchange].pairs;
|
|
45
|
+
|
|
46
|
+
for (const leftPairPart of Object.keys(pairs)) {
|
|
47
|
+
const symbols = pairs[leftPairPart].map(rightPairPart => {
|
|
48
|
+
const symbol = (0, _helpers.generateSymbol)(exchange, leftPairPart, rightPairPart);
|
|
49
|
+
return {
|
|
50
|
+
symbol: symbol.short,
|
|
51
|
+
full_name: symbol.full,
|
|
52
|
+
description: symbol.short,
|
|
53
|
+
exchange: exchange,
|
|
54
|
+
type: "crypto"
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
allSymbols = [...allSymbols, ...symbols];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return allSymbols;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
class Datafeed {}
|
|
64
|
+
|
|
65
|
+
exports.default = Datafeed;
|
|
66
|
+
|
|
67
|
+
_defineProperty(Datafeed, "onReady", callback => {
|
|
68
|
+
console.log("[onReady]: Method call");
|
|
69
|
+
setTimeout(() => callback(configurationData));
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
_defineProperty(Datafeed, "searchSymbols", async (userInput, exchange, symbolType, onResultReadyCallback) => {
|
|
73
|
+
console.log("[searchSymbols]: Method call");
|
|
74
|
+
const symbols = await getAllSymbols();
|
|
75
|
+
const newSymbols = symbols.filter(symbol => {
|
|
76
|
+
const isExchangeValid = exchange === "" || symbol.exchange === exchange;
|
|
77
|
+
const isFullSymbolContainsInput = symbol.full_name.toLowerCase().indexOf(userInput.toLowerCase()) !== -1;
|
|
78
|
+
return isExchangeValid && isFullSymbolContainsInput;
|
|
79
|
+
});
|
|
80
|
+
onResultReadyCallback(newSymbols);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
_defineProperty(Datafeed, "resolveSymbol", async (symbolName, onSymbolResolvedCallback, onResolveErrorCallback) => {
|
|
84
|
+
console.log("[resolveSymbol]: Method call", symbolName);
|
|
85
|
+
const symbols = await getAllSymbols();
|
|
86
|
+
const symbolItem = symbols.find(_ref => {
|
|
87
|
+
let {
|
|
88
|
+
full_name
|
|
89
|
+
} = _ref;
|
|
90
|
+
return full_name === symbolName;
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
if (!symbolItem) {
|
|
94
|
+
console.log("[resolveSymbol]: Cannot resolve symbol", symbolName);
|
|
95
|
+
onResolveErrorCallback("cannot resolve symbol");
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const symbolInfo = {
|
|
100
|
+
ticker: symbolItem.full_name,
|
|
101
|
+
name: symbolItem.symbol,
|
|
102
|
+
description: symbolItem.description,
|
|
103
|
+
type: symbolItem.type,
|
|
104
|
+
session: "24x7",
|
|
105
|
+
timezone: "Etc/UTC",
|
|
106
|
+
exchange: symbolItem.exchange,
|
|
107
|
+
minmov: 1,
|
|
108
|
+
pricescale: 100,
|
|
109
|
+
has_intraday: false,
|
|
110
|
+
has_no_volume: true,
|
|
111
|
+
has_weekly_and_monthly: false,
|
|
112
|
+
supported_resolutions: ["1D", "1W", "1M"],
|
|
113
|
+
volume_precision: 2,
|
|
114
|
+
data_status: "streaming"
|
|
115
|
+
};
|
|
116
|
+
console.log("[resolveSymbol]: Symbol resolved", symbolName);
|
|
117
|
+
onSymbolResolvedCallback(symbolInfo);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
_defineProperty(Datafeed, "getBars", async (symbolInfo, resolution, periodParams, onHistoryCallback, onErrorCallback) => {
|
|
121
|
+
const {
|
|
122
|
+
from,
|
|
123
|
+
to,
|
|
124
|
+
firstDataRequest
|
|
125
|
+
} = periodParams;
|
|
126
|
+
console.log("[getBars]: Method call", symbolInfo, resolution, from, to);
|
|
127
|
+
const parsedSymbol = (0, _helpers.parseFullSymbol)(symbolInfo.full_name);
|
|
128
|
+
const urlParameters = {
|
|
129
|
+
e: parsedSymbol.exchange,
|
|
130
|
+
fsym: parsedSymbol.fromSymbol,
|
|
131
|
+
tsym: parsedSymbol.toSymbol,
|
|
132
|
+
toTs: to,
|
|
133
|
+
limit: 2000
|
|
134
|
+
};
|
|
135
|
+
const query = Object.keys(urlParameters).map(name => "".concat(name, "=").concat(encodeURIComponent(urlParameters[name]))).join("&");
|
|
136
|
+
|
|
137
|
+
try {
|
|
138
|
+
const data = await (0, _helpers.makeApiRequest)("data/histoday?".concat(query));
|
|
139
|
+
|
|
140
|
+
if (data.Response && data.Response === "Error" || data.Data.length === 0) {
|
|
141
|
+
// "noData" should be set if there is no data in the requested period.
|
|
142
|
+
onHistoryCallback([], {
|
|
143
|
+
noData: true
|
|
144
|
+
});
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
let bars = [];
|
|
149
|
+
data.Data.forEach(bar => {
|
|
150
|
+
if (bar.time >= from && bar.time < to) {
|
|
151
|
+
bars = [...bars, {
|
|
152
|
+
time: bar.time * 1000,
|
|
153
|
+
low: bar.low,
|
|
154
|
+
high: bar.high,
|
|
155
|
+
open: bar.open,
|
|
156
|
+
close: bar.close
|
|
157
|
+
}];
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
if (firstDataRequest) {
|
|
162
|
+
lastBarsCache.set(symbolInfo.full_name, _objectSpread({}, bars[bars.length - 1]));
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
console.log("[getBars]: returned ".concat(bars.length, " bar(s)"));
|
|
166
|
+
onHistoryCallback(bars, {
|
|
167
|
+
noData: false
|
|
168
|
+
});
|
|
169
|
+
} catch (error) {
|
|
170
|
+
console.log("[getBars]: Get error", error);
|
|
171
|
+
onErrorCallback(error);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
_defineProperty(Datafeed, "subscribeBars", (symbolInfo, resolution, onRealtimeCallback, subscribeUID, onResetCacheNeededCallback) => {
|
|
176
|
+
console.log("[subscribeBars]: Method call with subscribeUID:", subscribeUID);
|
|
177
|
+
(0, _streaming.subscribeOnStream)(symbolInfo, resolution, onRealtimeCallback, subscribeUID, onResetCacheNeededCallback, lastBarsCache.get(symbolInfo.full_name));
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
_defineProperty(Datafeed, "unsubscribeBars", subscriberUID => {
|
|
181
|
+
console.log("[unsubscribeBars]: Method call with subscriberUID:", subscriberUID);
|
|
182
|
+
(0, _streaming.unsubscribeFromStream)(subscriberUID);
|
|
183
|
+
});
|
package/dist/helpers.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.generateSymbol = generateSymbol;
|
|
7
|
+
exports.makeApiRequest = makeApiRequest;
|
|
8
|
+
exports.parseFullSymbol = parseFullSymbol;
|
|
9
|
+
|
|
10
|
+
require("core-js/modules/es.promise.js");
|
|
11
|
+
|
|
12
|
+
require("core-js/modules/es.regexp.exec.js");
|
|
13
|
+
|
|
14
|
+
require("core-js/modules/es.string.match.js");
|
|
15
|
+
|
|
16
|
+
// Make requests to CryptoCompare API
|
|
17
|
+
async function makeApiRequest(path) {
|
|
18
|
+
try {
|
|
19
|
+
const response = await fetch("https://min-api.cryptocompare.com/".concat(path));
|
|
20
|
+
return response.json();
|
|
21
|
+
} catch (error) {
|
|
22
|
+
throw new Error("CryptoCompare request error: ".concat(error.status));
|
|
23
|
+
}
|
|
24
|
+
} // Generate a symbol ID from a pair of the coins
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
function generateSymbol(exchange, fromSymbol, toSymbol) {
|
|
28
|
+
const short = "".concat(fromSymbol, "/").concat(toSymbol);
|
|
29
|
+
return {
|
|
30
|
+
short,
|
|
31
|
+
full: "".concat(exchange, ":").concat(short)
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function parseFullSymbol(fullSymbol) {
|
|
36
|
+
const match = fullSymbol.match(/^(\w+):(\w+)\/(\w+)$/);
|
|
37
|
+
|
|
38
|
+
if (!match) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
exchange: match[1],
|
|
44
|
+
fromSymbol: match[2],
|
|
45
|
+
toSymbol: match[3]
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.subscribeOnStream = subscribeOnStream;
|
|
7
|
+
exports.unsubscribeFromStream = unsubscribeFromStream;
|
|
8
|
+
|
|
9
|
+
require("core-js/modules/web.dom-collections.iterator.js");
|
|
10
|
+
|
|
11
|
+
require("core-js/modules/es.regexp.exec.js");
|
|
12
|
+
|
|
13
|
+
require("core-js/modules/es.string.split.js");
|
|
14
|
+
|
|
15
|
+
require("core-js/modules/es.parse-int.js");
|
|
16
|
+
|
|
17
|
+
require("core-js/modules/es.parse-float.js");
|
|
18
|
+
|
|
19
|
+
var _helpers = require("./helpers.js");
|
|
20
|
+
|
|
21
|
+
var _socket = _interopRequireDefault(require("socket.io-client"));
|
|
22
|
+
|
|
23
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
24
|
+
|
|
25
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
26
|
+
|
|
27
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
28
|
+
|
|
29
|
+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
30
|
+
|
|
31
|
+
const socket = (0, _socket.default)("wss://streamer.cryptocompare.com");
|
|
32
|
+
const channelToSubscription = new Map();
|
|
33
|
+
socket.on("connect", () => {
|
|
34
|
+
console.log("[socket] Connected");
|
|
35
|
+
});
|
|
36
|
+
socket.on("disconnect", reason => {
|
|
37
|
+
console.log("[socket] Disconnected:", reason);
|
|
38
|
+
});
|
|
39
|
+
socket.on("error", error => {
|
|
40
|
+
console.log("[socket] Error:", error);
|
|
41
|
+
});
|
|
42
|
+
socket.on("m", data => {
|
|
43
|
+
console.log("[socket] Message:", data);
|
|
44
|
+
const [eventTypeStr, exchange, fromSymbol, toSymbol,,, tradeTimeStr,, tradePriceStr] = data.split("~");
|
|
45
|
+
|
|
46
|
+
if (parseInt(eventTypeStr) !== 0) {
|
|
47
|
+
// skip all non-TRADE events
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const tradePrice = parseFloat(tradePriceStr);
|
|
52
|
+
const tradeTime = parseInt(tradeTimeStr);
|
|
53
|
+
const channelString = "0~".concat(exchange, "~").concat(fromSymbol, "~").concat(toSymbol);
|
|
54
|
+
const subscriptionItem = channelToSubscription.get(channelString);
|
|
55
|
+
|
|
56
|
+
if (subscriptionItem === undefined) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const lastDailyBar = subscriptionItem.lastDailyBar;
|
|
61
|
+
const nextDailyBarTime = getNextDailyBarTime(lastDailyBar.time);
|
|
62
|
+
let bar;
|
|
63
|
+
|
|
64
|
+
if (tradeTime >= nextDailyBarTime) {
|
|
65
|
+
bar = {
|
|
66
|
+
time: nextDailyBarTime,
|
|
67
|
+
open: tradePrice,
|
|
68
|
+
high: tradePrice,
|
|
69
|
+
low: tradePrice,
|
|
70
|
+
close: tradePrice
|
|
71
|
+
};
|
|
72
|
+
console.log("[socket] Generate new bar", bar);
|
|
73
|
+
} else {
|
|
74
|
+
bar = _objectSpread(_objectSpread({}, lastDailyBar), {}, {
|
|
75
|
+
high: Math.max(lastDailyBar.high, tradePrice),
|
|
76
|
+
low: Math.min(lastDailyBar.low, tradePrice),
|
|
77
|
+
close: tradePrice
|
|
78
|
+
});
|
|
79
|
+
console.log("[socket] Update the latest bar by price", tradePrice);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
subscriptionItem.lastDailyBar = bar; // send data to every subscriber of that symbol
|
|
83
|
+
|
|
84
|
+
subscriptionItem.handlers.forEach(handler => handler.callback(bar));
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
function getNextDailyBarTime(barTime) {
|
|
88
|
+
const date = new Date(barTime * 1000);
|
|
89
|
+
date.setDate(date.getDate() + 1);
|
|
90
|
+
return date.getTime() / 1000;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function subscribeOnStream(symbolInfo, resolution, onRealtimeCallback, subscribeUID, onResetCacheNeededCallback, lastDailyBar) {
|
|
94
|
+
const parsedSymbol = (0, _helpers.parseFullSymbol)(symbolInfo.full_name);
|
|
95
|
+
const channelString = "0~".concat(parsedSymbol.exchange, "~").concat(parsedSymbol.fromSymbol, "~").concat(parsedSymbol.toSymbol);
|
|
96
|
+
const handler = {
|
|
97
|
+
id: subscribeUID,
|
|
98
|
+
callback: onRealtimeCallback
|
|
99
|
+
};
|
|
100
|
+
let subscriptionItem = channelToSubscription.get(channelString);
|
|
101
|
+
|
|
102
|
+
if (subscriptionItem) {
|
|
103
|
+
// already subscribed to the channel, use the existing subscription
|
|
104
|
+
subscriptionItem.handlers.push(handler);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
subscriptionItem = {
|
|
109
|
+
subscribeUID,
|
|
110
|
+
resolution,
|
|
111
|
+
lastDailyBar,
|
|
112
|
+
handlers: [handler]
|
|
113
|
+
};
|
|
114
|
+
channelToSubscription.set(channelString, subscriptionItem);
|
|
115
|
+
console.log("[subscribeBars]: Subscribe to streaming. Channel:", channelString);
|
|
116
|
+
socket.emit("SubAdd", {
|
|
117
|
+
subs: [channelString]
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function unsubscribeFromStream(subscriberUID) {
|
|
122
|
+
// find a subscription with id === subscriberUID
|
|
123
|
+
for (const channelString of channelToSubscription.keys()) {
|
|
124
|
+
const subscriptionItem = channelToSubscription.get(channelString);
|
|
125
|
+
const handlerIndex = subscriptionItem.handlers.findIndex(handler => handler.id === subscriberUID);
|
|
126
|
+
|
|
127
|
+
if (handlerIndex !== -1) {
|
|
128
|
+
// remove from handlers
|
|
129
|
+
subscriptionItem.handlers.splice(handlerIndex, 1);
|
|
130
|
+
|
|
131
|
+
if (subscriptionItem.handlers.length === 0) {
|
|
132
|
+
// unsubscribe from the channel, if it was the last handler
|
|
133
|
+
console.log("[unsubscribeBars]: Unsubscribe from streaming. Channel:", channelString);
|
|
134
|
+
socket.emit("SubRemove", {
|
|
135
|
+
subs: [channelString]
|
|
136
|
+
});
|
|
137
|
+
channelToSubscription.delete(channelString);
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.0.
|
|
2
|
+
"version": "0.0.5",
|
|
3
3
|
"name": "binbot-charts",
|
|
4
4
|
"dependencies": {
|
|
5
5
|
"@babel/cli": "^7.18.10",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
},
|
|
13
13
|
"scripts": {
|
|
14
14
|
"start": "react-scripts start",
|
|
15
|
-
"build": "rm -rf dist && NODE_ENV=production babel src/components
|
|
15
|
+
"build": "rm -rf dist && cp src/charting_library dist/charting_library NODE_ENV=production babel src/components --out-dir dist --copy-files",
|
|
16
16
|
"publish": "yarn build && npm publish"
|
|
17
17
|
},
|
|
18
18
|
"description": "Binbot charts is the default candlestick bars chart used in terminal.binbot.com to render bots graphically.",
|