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.Component {
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: "AAPL",
35
+ symbol: this.props.symbol,
36
36
  // BEWARE: no trailing slash is expected in feed URL
37
- datafeed: _datafeed.default,
38
- // interval: this.props.interval,
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
- // 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: {}
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
- const takeProfit = tvWidget.chart().createOrderLine().setText("Take profit").setLineLength(3).setLineStyle(1).setLineColor("green").setBodyBorderColor("green").setBodyTextColor("green").setQuantityBackgroundColor("green").setQuantityBorderColor("green").setQuantityTextColor("green").setQuantity("225 USDT");
56
- takeProfit.setPrice(182);
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
- exports.default = Datafeed;
66
-
67
- _defineProperty(Datafeed, "onReady", callback => {
68
- console.log("[onReady]: Method call");
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(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
- });
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(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
- }
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
- 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
- });
96
+ if (!symbolItem) {
97
+ console.log("[resolveSymbol]: Cannot resolve symbol", symbolName);
98
+ onResolveErrorCallback("cannot resolve symbol");
99
+ return;
100
+ }
119
101
 
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
- }
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
- 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
- }];
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
- if (firstDataRequest) {
162
- lastBarsCache.set(symbolInfo.full_name, _objectSpread({}, bars[bars.length - 1]));
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
- console.log("[getBars]: returned ".concat(bars.length, " bar(s)"));
166
- onHistoryCallback(bars, {
167
- noData: false
183
+ _defineProperty(this, "unsubscribeBars", subscriberUID => {
184
+ console.log("[unsubscribeBars]: Method call with subscriberUID:", subscriberUID);
185
+ (0, _streaming.unsubscribeFromStream)(subscriberUID);
168
186
  });
169
- } catch (error) {
170
- console.log("[getBars]: Get error", error);
171
- onErrorCallback(error);
187
+
188
+ this.timescaleMarks = timescaleMarks;
189
+ this.lineOrders = lineOrders;
172
190
  }
173
- });
174
191
 
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
- });
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
- _defineProperty(Datafeed, "unsubscribeBars", subscriberUID => {
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("./components/TVChartContainer"));
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,,, tradeTimeStr,, tradePriceStr] = data.split("~");
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.20",
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/lib/ -d dist && cp -r src/lib/charting_library dist/charting_library",
16
- "publish": "yarn build && npm publish"
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": ["dist"],
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"