sevencoin.js 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. localStorage.removeItem("tradingview.chartproperties");
  2. $(function () {
  3. let light = {
  4. "paneProperties.background": "#ffffff",
  5. "paneProperties.vertGridProperties.color": "#dcdee0",
  6. "paneProperties.horzGridProperties.color": "#dcdee0",
  7. "scalesProperties.backgroundColor": "#ffffff",
  8. "scalesProperties.lineColor": "#dcdee0",
  9. "scalesProperties.textColor": "#333",
  10. "scalesProperties.fontSize": 9,
  11. "mainSeriesProperties.style": 1,
  12. "paneProperties.legendProperties.showSeriesOHLC": false,
  13. };
  14. let dark = {
  15. // "paneProperties.background": "#2b2b37",
  16. "paneProperties.background": "#292944",
  17. "paneProperties.vertGridProperties.color": "#49495F",
  18. "paneProperties.horzGridProperties.color": "#49495F",
  19. // "scalesProperties.backgroundColor": "#2b2b37",
  20. "scalesProperties.backgroundColor": "#292944",
  21. "scalesProperties.textColor": "#fff",
  22. "scalesProperties.lineColor": "#49495F",
  23. "scalesProperties.fontSize": 9,
  24. "mainSeriesProperties.style": 1,
  25. "paneProperties.legendProperties.showSeriesOHLC": false,
  26. };
  27. let tvStyle = {
  28. light,
  29. dark,
  30. };
  31. class Datafeed {
  32. constructor(vm) {
  33. this.self = vm;
  34. }
  35. onReady(callback) {
  36. setTimeout(() => {
  37. callback({
  38. supports_search: false,
  39. supports_group_request: false,
  40. supported_resolutions: this.self.resolutions,
  41. supports_marks: true,
  42. supports_timescale_marks: true,
  43. supports_time: true,
  44. });
  45. }, 30);
  46. }
  47. resolveSymbol(
  48. symbolName,
  49. onSymbolResolvedCallback,
  50. onResolveErrorCallback
  51. ) {
  52. setTimeout(() => {
  53. let data = this.defaultSymbol();
  54. if (this.self.resolveSymbol) {
  55. this.self.resolveSymbol((res) => {
  56. onSymbolResolvedCallback(Object.assign(data, res));
  57. });
  58. } else {
  59. onSymbolResolvedCallback(data);
  60. }
  61. }, 60);
  62. }
  63. getBars() {
  64. this.self.getBars(...arguments);
  65. }
  66. subscribeBars() {
  67. this.self.subscribeBars(...arguments);
  68. }
  69. unsubscribeBars() {}
  70. defaultSymbol() {
  71. return {
  72. timezone: "Asia/Shanghai",
  73. minmov: 1,
  74. minmov2: 0,
  75. fractional: false,
  76. //设置周期
  77. session: "24x7",
  78. has_intraday: true,
  79. has_no_volume: false,
  80. //设置是否支持周月线
  81. has_daily: true,
  82. //设置是否支持周月线
  83. has_weekly_and_monthly: true,
  84. //设置精度 100表示保留两位小数 1000三位 10000四位
  85. pricescale: 10000,
  86. };
  87. }
  88. }
  89. class Page {
  90. constructor() {
  91. this.datafeed = undefined;
  92. this.page = 1;
  93. this.onRealtimeCallback = undefined;
  94. this.TView = undefined;
  95. this.interval = this.getQuery("interval");
  96. this.symbolName = this.getQuery("symbol");
  97. this.theme = this.getQuery("theme") || "dark";
  98. this.lang = this.getQuery("lang") || "en";
  99. this.resolutions = this.getQuery("resolutions") || [
  100. "5",
  101. "15",
  102. "30",
  103. "60",
  104. "1D",
  105. "1W",
  106. "1M",
  107. ];
  108. this.isLoad = false;
  109. this.url = this.getQuery("getLinkUrl");
  110. this.TVID = "tradingview_10798345";
  111. this.Ws = undefined;
  112. this.msg = "";
  113. this.contract = this.getQuery("contract");
  114. this.init();
  115. this.studies = []; //配置项
  116. }
  117. // 获取路劲上的参数
  118. getQuery(name) {
  119. let str = window.location.search.replace("?", "");
  120. let data = Qs.parse(str) || {};
  121. return data[name];
  122. }
  123. // 初始化
  124. init() {
  125. this.linkSocket();
  126. // 数据模型
  127. this.datafeed = new Datafeed(this);
  128. // 初始化图表
  129. this.TView = new TradingView.widget({
  130. fullscreen: false,
  131. autosize: true,
  132. interval: this.interval,
  133. timezone: "Asia/Shanghai",
  134. theme: "Dark", // 自定义主题
  135. // style: "1",
  136. library_path: "./chart_main/",
  137. datafeed: this.datafeed,
  138. // datafeed: {},
  139. locale: this.chartLang(),
  140. // toolbar_bg: this.theme == "light" ? "#fff" : "#2b2b37",
  141. toolbar_bg: this.theme == "light" ? "#fff" : "#292944",
  142. enable_publishing: false,
  143. withdateranges: false,
  144. hide_side_toolbar: false,
  145. allow_symbol_change: true,
  146. show_popup_button: true,
  147. hideideas: true,
  148. studies_overrides: {},
  149. container_id: "tradingview_10798345",
  150. disabled_features: [
  151. "header_symbol_search",
  152. "header_compare",
  153. "control_bar",
  154. "main_series_scale_menu",
  155. "volume_force_overlay",
  156. "header_resolutions",
  157. "legend_context_menu",
  158. "symbol_search_hot_key",
  159. "symbol_info",
  160. "pane_context_menu",
  161. ],
  162. overrides: tvStyle[this.theme],
  163. custom_css_url: this.theme == "light" ? "light-chart.css" : "chart.css",
  164. });
  165. this.TView.onChartReady(() => {
  166. this.TView.chart().createStudy("MACD", false, false);
  167. this.createStudy();
  168. });
  169. }
  170. createStudy() {
  171. let thats = this.TView;
  172. let id = thats
  173. .chart()
  174. .createStudy("Moving Average", false, false, [5], null, {
  175. "Plot.color": "rgb(150, 95, 196)",
  176. });
  177. this.studies.push(id);
  178. id = thats
  179. .chart()
  180. .createStudy("Moving Average", false, false, [10], null, {
  181. "Plot.color": "rgb(116,149,187)",
  182. });
  183. this.studies.push(id);
  184. id = thats
  185. .chart()
  186. .createStudy("Moving Average", false, false, [20], null, {
  187. "plot.color": "rgb(118,32,99)",
  188. });
  189. this.studies.push(id);
  190. }
  191. // 连接socket
  192. linkSocket() {
  193. // 连接socket
  194. this.Ws = new Ws(this.getQuery("ws"));
  195. this.Ws.on("message", (evt) => {
  196. if (evt.cmd == "ping") {
  197. this.Ws.send({ cmd: "pong" });
  198. }
  199. if (evt.type == "ping") {
  200. this.Ws.send({ cmd: "pong" });
  201. }
  202. // 追加数据
  203. // console.log(evt,evt.sub ,this.msg)
  204. if (evt.sub == this.msg) {
  205. this.onRealtimeCallback(this.getMap(evt.data));
  206. }
  207. });
  208. }
  209. // 图表语言映射
  210. chartLang() {
  211. switch (this.lang) {
  212. case "cn":
  213. return "zh";
  214. case "tw":
  215. return "zh_TW";
  216. case "tr":
  217. return "tr";
  218. case "jp":
  219. return "ja";
  220. case "kor":
  221. return "ko";
  222. case "de":
  223. return "de_DE";
  224. case "fra":
  225. return "fr";
  226. case "it":
  227. return "it";
  228. case "pt":
  229. return "pt";
  230. case "spa":
  231. return "es";
  232. default:
  233. return "en";
  234. }
  235. }
  236. getMap(data) {
  237. return {
  238. time: data.id * 1000,
  239. close: data.close * 1,
  240. open: data.open * 1,
  241. high: data.high * 1,
  242. low: data.low * 1,
  243. volume: data.vol * 1,
  244. };
  245. }
  246. resolveSymbol(call) {
  247. // 名称
  248. call({
  249. name: this.symbolName.toLocaleUpperCase(),
  250. description: this.symbolName.toLocaleUpperCase(),
  251. ticker: this.symbolName.toLocaleUpperCase(),
  252. supported_resolutions: this.resolutions,
  253. });
  254. }
  255. // 获取数据
  256. getBars(
  257. symbolInfo,
  258. resolution,
  259. rangeStartDate,
  260. rangeEndDate,
  261. onDataCallback,
  262. onErrorCallback
  263. ) {
  264. let page = this.page > 3 ? 3 : this.page;
  265. let data = {
  266. symbol: symbolInfo.name,
  267. period: this.resolution(resolution),
  268. form: rangeStartDate,
  269. to: rangeEndDate,
  270. size: page * 200,
  271. zip: 1,
  272. };
  273. this.page++;
  274. this.isLoad = true;
  275. this.unSub();
  276. $.get(this.url, data)
  277. .then((res) => {
  278. let arr = this.unzip(res.data.data).map((item) => {
  279. return this.getMap(item);
  280. });
  281. onDataCallback(arr);
  282. this.msg = this.createMsg();
  283. this.sub();
  284. })
  285. .catch((err) => {
  286. onDataCallback([]);
  287. });
  288. }
  289. // 解压
  290. unzip(b64Data) {
  291. let u8 = atob(b64Data);
  292. let jiya = pako.inflate(u8);
  293. let str = this.Uint8ArrayToString(jiya);
  294. return JSON.parse(str);
  295. }
  296. Uint8ArrayToString(fileData) {
  297. var dataString = "";
  298. for (var i = 0; i < fileData.length; i++) {
  299. dataString += String.fromCharCode(fileData[i]);
  300. }
  301. return dataString;
  302. }
  303. // 获取传给后台的精度
  304. resolution(resolution) {
  305. let T = "";
  306. if (isNaN(resolution * 1)) {
  307. T = resolution
  308. .replace("D", "day")
  309. .replace("W", "week")
  310. .replace("M", "mon");
  311. } else {
  312. if (resolution > 60) {
  313. T = Math.floor(resolution / 60) + "hours";
  314. } else {
  315. T = resolution + "min";
  316. }
  317. }
  318. return T;
  319. }
  320. // 获取推送回调
  321. subscribeBars(
  322. symbolInfo,
  323. resolution,
  324. onRealtimeCallback,
  325. subscriberUID,
  326. onResetCacheNeededCallback
  327. ) {
  328. this.onRealtimeCallback = onRealtimeCallback;
  329. if (!this.symbolName) {
  330. setTimeout(() => {
  331. onResetCacheNeededCallback();
  332. }, 100);
  333. }
  334. }
  335. getSymbol(name) {
  336. return name.split("/").join("").toLowerCase();
  337. }
  338. // 生成订阅数据
  339. createMsg() {
  340. if (this.contract) {
  341. return `swapKline_${this.symbolName}_${this.resolution(this.interval)}`;
  342. } else {
  343. return `Kline_${this.getSymbol(this.symbolName)}_${this.resolution(
  344. this.interval
  345. )}`;
  346. }
  347. }
  348. // 订阅消息
  349. sub() {
  350. this.Ws.send({
  351. cmd: "sub",
  352. msg: this.msg,
  353. });
  354. }
  355. // 取消订阅
  356. unSub() {
  357. if (!this.msg) return;
  358. this.Ws.send({
  359. cmd: "unsub",
  360. msg: this.msg,
  361. });
  362. }
  363. }
  364. new Page();
  365. });