binbot-charts 0.0.20 → 0.1.0
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
|
@@ -7,6 +7,8 @@ Import it in your project as a React component
|
|
|
7
7
|
## How to start
|
|
8
8
|
|
|
9
9
|
1. Run `yarn install && yarn start`. It will build the project and open a default browser with the Charting Library.
|
|
10
|
+
2. `library_path` should be `node_modules/dist/charting_library`
|
|
11
|
+
3. Write a script to copy `charting_library` to `public/charting_library` during build. E.g. `cp -r node_modules/dist/charting_library/ src/public/charting_library`
|
|
10
12
|
|
|
11
13
|
## About This Project
|
|
12
14
|
|
|
@@ -21,7 +21,7 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
|
|
|
21
21
|
|
|
22
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
23
|
|
|
24
|
-
class TVChartContainer extends _react.
|
|
24
|
+
class TVChartContainer extends _react.PureComponent {
|
|
25
25
|
constructor(props) {
|
|
26
26
|
super(props);
|
|
27
27
|
|
|
@@ -32,28 +32,27 @@ class TVChartContainer extends _react.Component {
|
|
|
32
32
|
|
|
33
33
|
componentDidMount() {
|
|
34
34
|
const widgetOptions = {
|
|
35
|
-
symbol:
|
|
35
|
+
symbol: this.props.symbol,
|
|
36
36
|
// BEWARE: no trailing slash is expected in feed URL
|
|
37
|
-
datafeed: _datafeed.default,
|
|
38
|
-
|
|
37
|
+
datafeed: new _datafeed.default(this.props.timescaleMarks),
|
|
38
|
+
interval: this.props.interval,
|
|
39
39
|
container: this.ref.current,
|
|
40
40
|
library_path: this.props.libraryPath,
|
|
41
41
|
locale: "en",
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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: {}
|
|
42
|
+
fullscreen: this.props.fullscreen,
|
|
43
|
+
autosize: this.props.autosize,
|
|
44
|
+
studies_overrides: this.props.studiesOverrides
|
|
51
45
|
};
|
|
52
46
|
const tvWidget = new _charting_library.widget(widgetOptions);
|
|
53
47
|
this.tvWidget = tvWidget;
|
|
54
48
|
tvWidget.onChartReady(() => {
|
|
55
|
-
|
|
56
|
-
|
|
49
|
+
this.props.orderLines.forEach(element => {
|
|
50
|
+
tvWidget.chart().createPositionLine().setText(element.text).setTooltip(element.tooltip) // .setProtectTooltip("Protect position")
|
|
51
|
+
// .setCloseTooltip("Close position")
|
|
52
|
+
// .setReverseTooltip("Reverse position")
|
|
53
|
+
.setQuantity(element.quantity).setQuantityBackgroundColor(element.color).setQuantityBorderColor(element.color) // .setExtendLeft(false)
|
|
54
|
+
.setLineStyle(0).setLineLength(25).setLineColor(element.color).setBodyBackgroundColor(element.color).setBodyBorderColor(element.color).setBodyTextColor(element.color).setPrice(element.price);
|
|
55
|
+
});
|
|
57
56
|
});
|
|
58
57
|
}
|
|
59
58
|
|
|
@@ -75,4 +74,18 @@ class TVChartContainer extends _react.Component {
|
|
|
75
74
|
|
|
76
75
|
}
|
|
77
76
|
|
|
78
|
-
exports.default = TVChartContainer;
|
|
77
|
+
exports.default = TVChartContainer;
|
|
78
|
+
|
|
79
|
+
_defineProperty(TVChartContainer, "defaultProps", {
|
|
80
|
+
symbol: "AAPL",
|
|
81
|
+
interval: "D",
|
|
82
|
+
datafeedUrl: "https://demo_feed.tradingview.com",
|
|
83
|
+
libraryPath: "/charting_library/",
|
|
84
|
+
chartsStorageUrl: "https://saveload.tradingview.com",
|
|
85
|
+
chartsStorageApiVersion: "1.1",
|
|
86
|
+
clientId: "tradingview.com",
|
|
87
|
+
userId: "public_user_id",
|
|
88
|
+
fullscreen: false,
|
|
89
|
+
autosize: true,
|
|
90
|
+
studiesOverrides: {}
|
|
91
|
+
});
|
|
@@ -24,6 +24,10 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
|
|
|
24
24
|
const lastBarsCache = new Map();
|
|
25
25
|
const exchange = "Binance";
|
|
26
26
|
const configurationData = {
|
|
27
|
+
// trading_options: true,
|
|
28
|
+
supports_marks: true,
|
|
29
|
+
supports_time: true,
|
|
30
|
+
supports_timescale_marks: true,
|
|
27
31
|
supported_resolutions: ["1D", "1W", "1M"],
|
|
28
32
|
exchanges: [{
|
|
29
33
|
value: "Binance",
|
|
@@ -32,10 +36,8 @@ const configurationData = {
|
|
|
32
36
|
}],
|
|
33
37
|
symbols_types: [{
|
|
34
38
|
name: "crypto",
|
|
35
|
-
// `symbolType` argument for the `searchSymbols` method, if a user selects this symbol type
|
|
36
39
|
value: "crypto"
|
|
37
|
-
}
|
|
38
|
-
]
|
|
40
|
+
}]
|
|
39
41
|
};
|
|
40
42
|
|
|
41
43
|
async function getAllSymbols() {
|
|
@@ -60,124 +62,142 @@ async function getAllSymbols() {
|
|
|
60
62
|
return allSymbols;
|
|
61
63
|
}
|
|
62
64
|
|
|
63
|
-
class Datafeed {
|
|
65
|
+
class Datafeed {
|
|
66
|
+
constructor() {
|
|
67
|
+
let timescaleMarks = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
68
|
+
let lineOrders = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
|
64
69
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
setTimeout(() => callback(configurationData));
|
|
70
|
-
});
|
|
70
|
+
_defineProperty(this, "onReady", callback => {
|
|
71
|
+
console.log("[onReady]: Method call");
|
|
72
|
+
setTimeout(() => callback(configurationData));
|
|
73
|
+
});
|
|
71
74
|
|
|
72
|
-
_defineProperty(
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
});
|
|
75
|
+
_defineProperty(this, "searchSymbols", async (userInput, exchange, symbolType, onResultReadyCallback) => {
|
|
76
|
+
console.log("[searchSymbols]: Method call");
|
|
77
|
+
const symbols = await getAllSymbols();
|
|
78
|
+
const newSymbols = symbols.filter(symbol => {
|
|
79
|
+
const isExchangeValid = exchange === "" || symbol.exchange === exchange;
|
|
80
|
+
const isFullSymbolContainsInput = symbol.full_name.toLowerCase().indexOf(userInput.toLowerCase()) !== -1;
|
|
81
|
+
return isExchangeValid && isFullSymbolContainsInput;
|
|
82
|
+
});
|
|
83
|
+
onResultReadyCallback(newSymbols);
|
|
84
|
+
});
|
|
82
85
|
|
|
83
|
-
_defineProperty(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (!symbolItem) {
|
|
94
|
-
console.log("[resolveSymbol]: Cannot resolve symbol", symbolName);
|
|
95
|
-
onResolveErrorCallback("cannot resolve symbol");
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
86
|
+
_defineProperty(this, "resolveSymbol", async (symbolName, onSymbolResolvedCallback, onResolveErrorCallback) => {
|
|
87
|
+
console.log("[resolveSymbol]: Method call", symbolName);
|
|
88
|
+
const symbols = await getAllSymbols();
|
|
89
|
+
const symbolItem = symbols.find(_ref => {
|
|
90
|
+
let {
|
|
91
|
+
full_name
|
|
92
|
+
} = _ref;
|
|
93
|
+
return full_name === symbolName;
|
|
94
|
+
});
|
|
98
95
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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
|
-
});
|
|
96
|
+
if (!symbolItem) {
|
|
97
|
+
console.log("[resolveSymbol]: Cannot resolve symbol", symbolName);
|
|
98
|
+
onResolveErrorCallback("cannot resolve symbol");
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
119
101
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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
|
-
}
|
|
102
|
+
const symbolInfo = {
|
|
103
|
+
ticker: symbolItem.full_name,
|
|
104
|
+
name: symbolItem.symbol,
|
|
105
|
+
description: symbolItem.description,
|
|
106
|
+
type: symbolItem.type,
|
|
107
|
+
session: "24x7",
|
|
108
|
+
timezone: "Etc/UTC",
|
|
109
|
+
exchange: symbolItem.exchange,
|
|
110
|
+
minmov: 1,
|
|
111
|
+
pricescale: 100,
|
|
112
|
+
has_intraday: true,
|
|
113
|
+
has_no_volume: false,
|
|
114
|
+
has_weekly_and_monthly: false,
|
|
115
|
+
supported_resolutions: ["1D", "1W", "1M"],
|
|
116
|
+
volume_precision: 4,
|
|
117
|
+
data_status: "streaming"
|
|
118
|
+
};
|
|
119
|
+
console.log("[resolveSymbol]: Symbol resolved", symbolName);
|
|
120
|
+
onSymbolResolvedCallback(symbolInfo);
|
|
121
|
+
});
|
|
147
122
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
123
|
+
_defineProperty(this, "getBars", async (symbolInfo, resolution, periodParams, onHistoryCallback, onErrorCallback) => {
|
|
124
|
+
const {
|
|
125
|
+
from,
|
|
126
|
+
to,
|
|
127
|
+
firstDataRequest
|
|
128
|
+
} = periodParams;
|
|
129
|
+
console.log("[getBars]: Method call");
|
|
130
|
+
const parsedSymbol = (0, _helpers.parseFullSymbol)(symbolInfo.full_name);
|
|
131
|
+
const urlParameters = {
|
|
132
|
+
e: parsedSymbol.exchange,
|
|
133
|
+
fsym: parsedSymbol.fromSymbol,
|
|
134
|
+
tsym: parsedSymbol.toSymbol,
|
|
135
|
+
toTs: to,
|
|
136
|
+
limit: 2000
|
|
137
|
+
};
|
|
138
|
+
const query = Object.keys(urlParameters).map(name => "".concat(name, "=").concat(encodeURIComponent(urlParameters[name]))).join("&");
|
|
139
|
+
|
|
140
|
+
try {
|
|
141
|
+
const data = await (0, _helpers.makeApiRequest)("data/histoday?".concat(query));
|
|
142
|
+
|
|
143
|
+
if (data.Response && data.Response === "Error" || data.Data.length === 0) {
|
|
144
|
+
// "noData" should be set if there is no data in the requested period.
|
|
145
|
+
onHistoryCallback([], {
|
|
146
|
+
noData: true
|
|
147
|
+
});
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
let bars = [];
|
|
152
|
+
data.Data.forEach(bar => {
|
|
153
|
+
if (bar.time >= from && bar.time < to) {
|
|
154
|
+
bars = [...bars, {
|
|
155
|
+
time: bar.time * 1000,
|
|
156
|
+
low: bar.low,
|
|
157
|
+
high: bar.high,
|
|
158
|
+
open: bar.open,
|
|
159
|
+
close: bar.close
|
|
160
|
+
}];
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
if (firstDataRequest) {
|
|
165
|
+
lastBarsCache.set(symbolInfo.full_name, _objectSpread({}, bars[bars.length - 1]));
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
console.log("[getBars]: returned ".concat(bars.length, " bar(s)"));
|
|
169
|
+
onHistoryCallback(bars, {
|
|
170
|
+
noData: false
|
|
171
|
+
});
|
|
172
|
+
} catch (error) {
|
|
173
|
+
console.log("[getBars]: Get error", error);
|
|
174
|
+
onErrorCallback(error);
|
|
158
175
|
}
|
|
159
176
|
});
|
|
160
177
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
178
|
+
_defineProperty(this, "subscribeBars", (symbolInfo, resolution, onRealtimeCallback, subscribeUID, onResetCacheNeededCallback) => {
|
|
179
|
+
console.log("[subscribeBars]: Method call with subscribeUID:", subscribeUID);
|
|
180
|
+
(0, _streaming.subscribeOnStream)(symbolInfo, resolution, onRealtimeCallback, subscribeUID, onResetCacheNeededCallback, lastBarsCache.get(symbolInfo.full_name));
|
|
181
|
+
});
|
|
164
182
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
183
|
+
_defineProperty(this, "unsubscribeBars", subscriberUID => {
|
|
184
|
+
console.log("[unsubscribeBars]: Method call with subscriberUID:", subscriberUID);
|
|
185
|
+
(0, _streaming.unsubscribeFromStream)(subscriberUID);
|
|
168
186
|
});
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
187
|
+
|
|
188
|
+
this.timescaleMarks = timescaleMarks;
|
|
189
|
+
this.lineOrders = lineOrders;
|
|
172
190
|
}
|
|
173
|
-
});
|
|
174
191
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
192
|
+
getTimescaleMarks(symbolInfo, from, to, onDataCallback, resolution) {
|
|
193
|
+
let timescaleMarks = [];
|
|
194
|
+
|
|
195
|
+
if (this.timescaleMarks.length > 0) {
|
|
196
|
+
timescaleMarks = this.timescaleMarks;
|
|
197
|
+
onDataCallback(timescaleMarks);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
}
|
|
179
202
|
|
|
180
|
-
|
|
181
|
-
console.log("[unsubscribeBars]: Method call with subscriberUID:", subscriberUID);
|
|
182
|
-
(0, _streaming.unsubscribeFromStream)(subscriberUID);
|
|
183
|
-
});
|
|
203
|
+
exports.default = Datafeed;
|
|
@@ -10,6 +10,6 @@ Object.defineProperty(exports, "TVChartContainer", {
|
|
|
10
10
|
}
|
|
11
11
|
});
|
|
12
12
|
|
|
13
|
-
var _TVChartContainer = _interopRequireDefault(require("./
|
|
13
|
+
var _TVChartContainer = _interopRequireDefault(require("./TVChartContainer"));
|
|
14
14
|
|
|
15
15
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -41,7 +41,7 @@ socket.on("error", error => {
|
|
|
41
41
|
});
|
|
42
42
|
socket.on("m", data => {
|
|
43
43
|
console.log("[socket] Message:", data);
|
|
44
|
-
const [eventTypeStr, exchange, fromSymbol, toSymbol
|
|
44
|
+
const [eventTypeStr, exchange, fromSymbol, toSymbol, tradeTimeStr, tradePriceStr] = data.split("~");
|
|
45
45
|
|
|
46
46
|
if (parseInt(eventTypeStr) !== 0) {
|
|
47
47
|
// skip all non-TRADE events
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.0
|
|
2
|
+
"version": "0.1.0",
|
|
3
3
|
"name": "binbot-charts",
|
|
4
4
|
"dependencies": {
|
|
5
5
|
"@babel/cli": "^7.18.10",
|
|
@@ -8,21 +8,24 @@
|
|
|
8
8
|
"@babel/preset-env": "^7.18.10",
|
|
9
9
|
"react": "^17.0.1",
|
|
10
10
|
"react-dom": "^17.0.1",
|
|
11
|
-
"react-scripts": "5.0.1"
|
|
11
|
+
"react-scripts": "5.0.1",
|
|
12
|
+
"socket.io-client": "^4.5.2"
|
|
12
13
|
},
|
|
13
14
|
"scripts": {
|
|
14
15
|
"start": "react-scripts start",
|
|
15
|
-
"build": "rm -rf dist && NODE_ENV=production babel src/
|
|
16
|
-
"
|
|
16
|
+
"build": "rm -rf dist && NODE_ENV=production babel src/components/ -d dist/components && cp -r src/charting_library dist/charting_library",
|
|
17
|
+
"release": "yarn build && npm publish"
|
|
17
18
|
},
|
|
18
19
|
"description": "Binbot charts is the default candlestick bars chart used in terminal.binbot.com to render bots graphically.",
|
|
19
20
|
"repository": {
|
|
20
21
|
"type": "git",
|
|
21
22
|
"url": "git+https://github.com/carkod/binbot-charts.git"
|
|
22
23
|
},
|
|
23
|
-
"module": "dist/index.js",
|
|
24
|
-
"main": "dist/index.js",
|
|
25
|
-
"files": [
|
|
24
|
+
"module": "dist/components/index.js",
|
|
25
|
+
"main": "dist/components/index.js",
|
|
26
|
+
"files": [
|
|
27
|
+
"dist"
|
|
28
|
+
],
|
|
26
29
|
"keywords": [
|
|
27
30
|
"binbot",
|
|
28
31
|
"charts"
|