totalProfitCalc.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571
  1. const Logs = require('../libs/logs');
  2. const { eventSolutions } = require('./eventSolutions');
  3. /**
  4. * 精确浮点数字
  5. * @param {number} number
  6. * @param {number} x
  7. * @returns {number}
  8. */
  9. const fixFloat = (number, x = 2) => {
  10. return parseFloat(number.toFixed(x));
  11. }
  12. /**
  13. * 获取内盘位置
  14. */
  15. const getBetSide = (bet_index) => {
  16. switch (bet_index) {
  17. case 0:
  18. return 'side_a';
  19. case 1:
  20. return 'side_b';
  21. case 2:
  22. return 'side_c';
  23. }
  24. return undefined;
  25. }
  26. /**
  27. * 盘口输赢映射
  28. */
  29. const CROSS_TYPE_MAP = { w: 1, l: -1, a: 1, h: 0.5, d: 0, r: 0, v: 0 };
  30. const getCrossTypeList = (cross_type) => {
  31. return cross_type.split('_').map(part => {
  32. return part.split('').map(key => CROSS_TYPE_MAP[key]);
  33. }).map(([a, b])=> a * b);
  34. }
  35. /**
  36. * 计算输赢比例
  37. */
  38. const getWinProportion = (sol, bet_index) => {
  39. const typeList = getCrossTypeList(sol.cross_type);
  40. const betSide = getBetSide(bet_index);
  41. let win_proportion = 0;
  42. if (typeList[bet_index] <= 0) {
  43. // 输或平
  44. win_proportion = typeList[bet_index] * (1 - sol[`rebate_${betSide}`]);
  45. }
  46. else {
  47. // 赢
  48. if (sol[`rebate_type_${betSide}`] == 1) {
  49. // 按本金返水
  50. win_proportion = typeList[bet_index] * (sol[`odds_${betSide}`] + sol[`rebate_${betSide}`]);
  51. }
  52. else {
  53. // 按结算返水
  54. win_proportion = typeList[bet_index] * sol[`odds_${betSide}`] * (1 + sol[`rebate_${betSide}`]);
  55. }
  56. }
  57. return win_proportion;
  58. }
  59. /**
  60. * 计算盘口输的比例
  61. */
  62. const lossProportion = (sol) => {
  63. const loss_proportion_a = getWinProportion(sol, 0) * -1;
  64. const loss_proportion_b = getWinProportion(sol, 1) * -1;
  65. return { loss_proportion_a, loss_proportion_b };
  66. }
  67. /**
  68. * 外盘特殊盘赢时的内盘剩余额度
  69. */
  70. const getInnerWinGoldsWithSpecialWin = (sol) => {
  71. const { inner_base, inner_index } = sol;
  72. const win_proportion = getWinProportion(sol, inner_index);
  73. const inner_win_golds = win_proportion * inner_base;
  74. return fixFloat(inner_base + inner_win_golds);
  75. }
  76. /**
  77. * 不同组合的金额计算
  78. */
  79. const HandicapCalc = function (data) {
  80. // console.log('HandicapCalc', data);
  81. const { i, g, r, a, b, c, A, B, C, TA, TB, TC, w, l } = data;
  82. const t = w + l;
  83. const k0 = 1 - r;
  84. const k1 = TA == 1 ? a + A : a * (1 + A);
  85. const k2 = 1 - A;
  86. const k3 = TB == 1 ? b + B : b * (1 + B);
  87. const k4 = 1 - B;
  88. const k5 = TC == 1 ? c + C : c * (1 + C);
  89. const k6 = 1 - C;
  90. const calcTemplate = (handlers) => {
  91. if (i > 2 || i < 0) {
  92. return {};
  93. }
  94. if (i === 2) {
  95. const z = g;
  96. const m = t + k6 * z;
  97. // const m = t + k0 * z;
  98. const x = (k3 + k4) * m / (k1 * k3 - k2 * k4);
  99. const y = (k1 + k2) * m / (k1 * k3 - k2 * k4);
  100. return { x, y, z };
  101. };
  102. return handlers[i]?.() ?? {};
  103. };
  104. return {
  105. la_wh_wa() {
  106. return calcTemplate([
  107. () => {
  108. const x = g;
  109. const m = t + k2 * x;
  110. // const m = t + k0 * x;
  111. const z = m / (2 * k5 + k6);
  112. const y = (k5 + k6) * m / (k3 * k5 + k3 * k6 / 2);
  113. return { x, y, z };
  114. },
  115. () => {
  116. const y = g;
  117. const z = ((k1 + k2) * t + (k2 * k4 - k1 * k3 / 2) * y) / (k1 * k5 - k2 * k6);
  118. const x = ((k5 + k6) * t + (k4 * k5 - k3 * k6 / 2) * y) / (k1 * k5 - k2 * k6);
  119. // const z = ((k1 + k2) * t + (k0 * k2 - k1 * k3 / 2) * y) / (k1 * k5 - k2 * k6);
  120. // const x = ((k5 + k6) * t + (k0 * k5 - k3 * k6 / 2) * y) / (k1 * k5 - k2 * k6);
  121. return { x, y, z };
  122. }
  123. ]);
  124. },
  125. la_dr_wa() {
  126. return calcTemplate([
  127. () => {
  128. const x = g;
  129. const m = t + k2 * x;
  130. // const m = t + k0 * x;
  131. const z = m / k5;
  132. const y = (k5 + k6) * m / (k3 * k5);
  133. return { x, y, z };
  134. },
  135. () => {
  136. const y = g;
  137. const z = ((k1 + k2) * t + k2 * k4 * y) / (k1 * k5 - k2 * k6);
  138. const x = ((k5 + k6) * t + k4 * k5 * y) / (k1 * k5 - k2 * k6);
  139. // const z = ((k1 + k2) * t + k0 * k2 * y) / (k1 * k5 - k2 * k6);
  140. // const x = ((k5 + k6) * t + k0 * k5 * y) / (k1 * k5 - k2 * k6);
  141. return { x, y, z };
  142. }
  143. ]);
  144. },
  145. la_lh_wa() {
  146. return calcTemplate([
  147. () => {
  148. const x = g;
  149. const m = t + k2 * x;
  150. // const m = t + k0 * x;
  151. const z = (2 * k3 + k4) * m / (2 * k3 * k5 - k4 * k6);
  152. const y = (k5 + k6) * m / (k3 * k5 - k4 * k6 / 2);
  153. return { x, y, z };
  154. },
  155. () => {
  156. const y = g;
  157. const z = ((k1 + k2) * t + (k2 * k4 + k1 * k4 / 2) * y) / (k1 * k5 - k2 * k6);
  158. const x = ((k5 + k6) * t + (k4 * k5 + k4 * k6 / 2) * y) / (k1 * k5 - k2 * k6);
  159. // const z = ((k1 + k2) * t + (k0 * k2 + k1 * k4 / 2) * y) / (k1 * k5 - k2 * k6);
  160. // const x = ((k5 + k6) * t + (k0 * k5 + k4 * k6 / 2) * y) / (k1 * k5 - k2 * k6);
  161. return { x, y, z };
  162. }
  163. ]);
  164. },
  165. lh_dr_wa() {
  166. return calcTemplate([
  167. () => {
  168. const x = g;
  169. const z = (t + k2 * x / 2) / k5;
  170. const y = ((k5 + k6) * t + (k5 + k6 / 2) * k2 * x) / (k3 * k5);
  171. // const y = ((k5 + k6) * t + (k0 * k5 + k2 * k6 / 2) * x) / (k3 * k5);
  172. return { x, y, z };
  173. },
  174. () => {
  175. const y = g;
  176. const z = ((2 * k1 + k2) * t + k2 * k4 * y) / (2 * k1 * k5 - k2 * k6);
  177. const x = ((k5 + k6) * t + k4 * k5 * y) / (k1 * k5 - k2 * k6 / 2);
  178. // const z = ((2 * k1 + k2) * t + k0 * k2 * y) / (2 * k1 * k5 - k2 * k6);
  179. // const x = ((k5 + k6) * t + k0 * k5 * y) / (k1 * k5 - k2 * k6 / 2);
  180. return { x, y, z };
  181. }
  182. ]);
  183. },
  184. lh_lh_wa() {
  185. return calcTemplate([
  186. () => {
  187. const x = g;
  188. const z = ((2 * k3 + k4) * t + (k3 + k4) * k2 * x) / (2 * k3 * k5 - k4 * k6);
  189. const y = ((k5 + k6) * t + (k5 + k6 / 2) * k2 * x) / (k3 * k5 - k4 * k6 / 2);
  190. // const z = ((2 * k3 + k4) * t + (k0 * k4 + k2 * k3) * x) / (2 * k3 * k5 - k4 * k6);
  191. // const y = ((k5 + k6) * t + (k0 * k5 + k2 * k6 / 2) * x) / (k3 * k5 - k4 * k6 / 2);
  192. return { x, y, z };
  193. },
  194. () => {
  195. const y = g;
  196. const z = ((2 * k1 + k2) * t + (k1 + k2) * k4 * y) / (2 * k1 * k5 - k2 * k6);
  197. const x = ((k5 + k6) * t + (k5 + k6 / 2) * k4 * y) / (k1 * k5 - k2 * k6 / 2);
  198. // const z = ((2 * k1 + k2) * t + (k0 * k2 + k1 * k4) * y) / (2 * k1 * k5 - k2 * k6);
  199. // const x = ((k5 + k6) * t + (k0 * k5 + k4 * k6 / 2) * y) / (k1 * k5 - k2 * k6 / 2);
  200. return { x, y, z };
  201. }
  202. ]);
  203. },
  204. la_la_wa() {
  205. return calcTemplate([
  206. () => {
  207. const x = g;
  208. const m = t + k2 * x;
  209. // const m = t + k0 * x;
  210. const z = (k3 + k4) * m / (k3 * k5 - k4 * k6);
  211. const y = (k5 + k6) * m / (k3 * k5 - k4 * k6);
  212. return { x, y, z };
  213. },
  214. () => {
  215. const y = g;
  216. const m = t + k4 * y;
  217. // const m = t + k0 * y;
  218. const z = (k1 + k2) * m / (k1 * k5 - k2 * k6);
  219. const x = (k5 + k6) * m / (k1 * k5 - k2 * k6);
  220. return { x, y, z };
  221. }
  222. ]);
  223. },
  224. la_wa_rv() {
  225. return calcTemplate([
  226. () => {
  227. const x = g;
  228. const y = (k2 * x + t) / k3;
  229. // const y = (k0 * x + t) / k3;
  230. const z = 0;
  231. return { x, y, z };
  232. },
  233. () => {
  234. const y = g;
  235. const x = (k4 * y + t) / k1;
  236. // const x = (k0 * y + t) / k1;
  237. const z = 0;
  238. return { x, y, z };
  239. }
  240. ]);
  241. }
  242. }
  243. }
  244. /**
  245. * 根据预期盈利计算下注金额
  246. */
  247. const calcGoldsWithTarget = (data) => {
  248. const {
  249. inner_index: i,
  250. inner_base: g,
  251. inner_rebate: r,
  252. odds_side_a: a,
  253. odds_side_b: b,
  254. odds_side_c: c,
  255. rebate_side_a: A,
  256. rebate_side_b: B,
  257. rebate_side_c: C,
  258. rebate_type_side_a: TA,
  259. rebate_type_side_b: TB,
  260. rebate_type_side_c: TC,
  261. cross_type: t,
  262. win_target: w,
  263. loss_out: l = 0,
  264. } = data;
  265. const calc = new HandicapCalc({ i, g, r, a, b, c, A, B, C, TA, TB, TC, w, l });
  266. const { x, y, z } = calc?.[t]() ?? {};
  267. return {
  268. gold_side_a: fixFloat(x),
  269. gold_side_b: fixFloat(y),
  270. gold_side_c: fixFloat(z),
  271. }
  272. }
  273. /**
  274. * 根据预期盈利计算金额和内盘盈亏
  275. */
  276. const calcWinResultWithTarget = (data) => {
  277. const { inner_base, inner_rebate, win_target, sol1, sol2 } = data;
  278. const {
  279. cross_type: crossType1,
  280. odds_side_a: oddsA1,
  281. odds_side_b: oddsB1,
  282. odds_side_c: oddsC1,
  283. rebate_side_a: rebateA1,
  284. rebate_side_b: rebateB1,
  285. rebate_side_c: rebateC1,
  286. rebate_type_side_a: rebateTypeA1,
  287. rebate_type_side_b: rebateTypeB1,
  288. rebate_type_side_c: rebateTypeC1,
  289. inner_index: inner_index_1,
  290. } = sol1;
  291. const innerSide1 = getBetSide(inner_index_1);
  292. const innerOdds1 = sol1[`odds_${innerSide1}`];
  293. const innerRebateTotal = inner_rebate ?? sol1[`rebate_${innerSide1}`];
  294. const innerRebateActual = fixFloat(innerRebateTotal / (innerOdds1 + 2), 3);
  295. const firstSolData = { ...sol1, inner_base, inner_rebate: innerRebateTotal, win_target };
  296. firstSolData[`rebate_${innerSide1}`] = innerRebateActual;
  297. const {
  298. gold_side_a: goldA1,
  299. gold_side_b: goldB1,
  300. gold_side_c: goldC1,
  301. } = calcGoldsWithTarget(firstSolData);
  302. let loss_out_1 = 0;
  303. switch (inner_index_1) {
  304. case 0:
  305. loss_out_1 = goldB1 * (1 - rebateB1) + goldC1 * (1 - rebateC1);
  306. break;
  307. case 1:
  308. loss_out_1 = goldA1 * (1 - rebateA1) + goldC1 * (1 - rebateC1);
  309. break;
  310. case 2:
  311. const { loss_proportion_a: lpA1, loss_proportion_b: lpB1 } = lossProportion(sol1);
  312. loss_out_1 = goldA1 * lpA1 + goldB1 * lpB1;
  313. break;
  314. }
  315. loss_out_1 = fixFloat(loss_out_1);
  316. const {
  317. cross_type: crossType2,
  318. odds_side_a: oddsA2,
  319. odds_side_b: oddsB2,
  320. odds_side_c: oddsC2,
  321. rebate_side_a: rebateA2,
  322. rebate_side_b: rebateB2,
  323. rebate_side_c: rebateC2,
  324. rebate_type_side_a: rebateTypeA2,
  325. rebate_type_side_b: rebateTypeB2,
  326. rebate_type_side_c: rebateTypeC2,
  327. inner_index: inner_index_2,
  328. } = sol2;
  329. const innerSide2 = getBetSide(inner_index_2);
  330. const innerOdds2 = (sol2[`odds_${innerSide2}`] + 1) * (innerOdds1 + 1) - 1;
  331. const secondSolData = { ...sol2, inner_base, inner_rebate: innerRebateTotal, win_target, loss_out: loss_out_1 };
  332. secondSolData[`odds_${innerSide2}`] = innerOdds2;
  333. secondSolData[`rebate_${innerSide2}`] = innerRebateActual;
  334. const {
  335. gold_side_a: goldA2,
  336. gold_side_b: goldB2,
  337. gold_side_c: goldC2,
  338. } = calcGoldsWithTarget(secondSolData);
  339. const win_inner_2 = inner_base * (innerOdds2 + 1 + innerRebateTotal);
  340. let loss_out_2 = 0, inner_base_key;
  341. switch (inner_index_2) {
  342. case 0:
  343. inner_base_key = 'goldA2';
  344. loss_out_2 = goldB2 * (1 - rebateB2) + goldC2 * (1 - rebateC2) + loss_out_1;
  345. break;
  346. case 1:
  347. inner_base_key = 'goldB2';
  348. loss_out_2 = goldA2 * (1 - rebateA2) + goldC2 * (1 - rebateC2) + loss_out_1;
  349. break;
  350. case 2:
  351. const { loss_proportion_a: lpA2, loss_proportion_b: lpB2 } = lossProportion(sol2);
  352. inner_base_key = 'goldC2';
  353. loss_out_2 = goldA2 * lpA2 + goldB2 * lpB2 + loss_out_1;
  354. break;
  355. }
  356. const win_inner = fixFloat(win_inner_2 - loss_out_2);
  357. const goldsInfo = { goldA1, goldB1, goldC1, goldA2, goldB2, goldC2 }
  358. // if (goldsInfo[inner_base_key]) {
  359. // goldsInfo[inner_base_key] = win_inner_1;
  360. // }
  361. const result = {
  362. bet_info: [
  363. {
  364. cross_type: crossType1,
  365. gold_side_a: goldsInfo.goldA1,
  366. gold_side_b: goldsInfo.goldB1,
  367. gold_side_c: goldsInfo.goldC1,
  368. odds_side_a: oddsA1,
  369. odds_side_b: oddsB1,
  370. odds_side_c: oddsC1,
  371. rebate_side_a: rebateA1,
  372. rebate_side_b: rebateB1,
  373. rebate_side_c: rebateC1,
  374. rebate_type_side_a: rebateTypeA1,
  375. rebate_type_side_b: rebateTypeB1,
  376. rebate_type_side_c: rebateTypeC1,
  377. inner_index: inner_index_1,
  378. },
  379. {
  380. cross_type: crossType2,
  381. gold_side_a: goldsInfo.goldA2,
  382. gold_side_b: goldsInfo.goldB2,
  383. gold_side_c: goldsInfo.goldC2,
  384. odds_side_a: oddsA2,
  385. odds_side_b: oddsB2,
  386. odds_side_c: oddsC2,
  387. rebate_side_a: rebateA2,
  388. rebate_side_b: rebateB2,
  389. rebate_side_c: rebateC2,
  390. rebate_type_side_a: rebateTypeA2,
  391. rebate_type_side_b: rebateTypeB2,
  392. rebate_type_side_c: rebateTypeC2,
  393. inner_index: inner_index_2,
  394. }
  395. ],
  396. win_inner,
  397. inner_base,
  398. inner_rebate,
  399. }
  400. return result;
  401. }
  402. /**
  403. * 根据单关盈亏计算综合利润
  404. */
  405. const calcTotalProfit = (sol1, sol2, inner_base, inner_rebate) => {
  406. // const rebateInner = inner_base * inner_rebate;
  407. const winTarget1 = fixFloat(sol1.win_average);
  408. const winTarget2 = fixFloat(sol2.win_average);
  409. const winTarget = fixFloat(Math.min(winTarget1, winTarget2));
  410. const win1 = calcWinResultWithTarget({ inner_base, inner_rebate, win_target: winTarget1, sol1, sol2 })?.win_inner;
  411. const win2 = calcWinResultWithTarget({ inner_base, inner_rebate, win_target: winTarget2, sol1, sol2 })?.win_inner;
  412. const win_inner = fixFloat(Math.max(win1, win2), 2);
  413. const start = Math.max(winTarget, win_inner);
  414. const end = Math.min(winTarget, win_inner);
  415. const result = [];
  416. for (let i = start; i > end; i--) {
  417. const win_target = i;
  418. const goldsInfo = calcWinResultWithTarget({ inner_base, inner_rebate, win_target, sol1, sol2 });
  419. const { win_inner, ...goldsRest } = goldsInfo;
  420. const win_diff = Math.abs(fixFloat(win_target - goldsInfo.win_inner));
  421. const lastResult = result.at(-1);
  422. if (!lastResult?.win_diff || win_diff < lastResult.win_diff) {
  423. result.push({ win_target: fixFloat(win_target), win_diff, win_inner: fixFloat(win_inner), ...goldsRest });
  424. }
  425. else {
  426. break;
  427. }
  428. }
  429. return result.at(-1);
  430. }
  431. /**
  432. * ----------------------------
  433. * 计算第一关锁定之后的新利润
  434. * 第一关过关后,重新计算第二关金额
  435. * 结合第一关亏损计算第二关新利润
  436. * ----------------------------
  437. */
  438. /**
  439. * 计算第二关利润
  440. */
  441. const calcSecondProfit = (betInfo) => {
  442. const {
  443. inner_index, inner_odds_first,
  444. odds_side_a: a, odds_side_b: b, odds_side_c: c,
  445. } = betInfo;
  446. let odds_side_a, odds_side_b, odds_side_c;
  447. switch (inner_index) {
  448. case 0:
  449. odds_side_a = fixFloat((a+1) * (inner_odds_first+1) - 1);
  450. odds_side_b = b;
  451. odds_side_c = c;
  452. break;
  453. case 1:
  454. odds_side_a = a;
  455. odds_side_b = fixFloat((b+1) * (inner_odds_first+1) - 1);
  456. odds_side_c = c;
  457. break;
  458. case 2:
  459. odds_side_a = a;
  460. odds_side_b = b;
  461. odds_side_c = fixFloat((c+1) * (inner_odds_first+1) - 1);
  462. break;
  463. }
  464. return eventSolutions({ ...betInfo, odds_side_a, odds_side_b, odds_side_c }, true);
  465. }
  466. /**
  467. * 获取第一关内盘信息及外盘损失
  468. */
  469. const getFirstInfo = (betInfo) => {
  470. const {
  471. inner_index,
  472. gold_side_a, gold_side_b, gold_side_c,
  473. odds_side_a, odds_side_b, odds_side_c,
  474. rebate_side_a, rebate_side_b, rebate_side_c,
  475. } = betInfo;
  476. let loss_out = 0, inner_ref_value = 0, inner_odds = 0;
  477. switch (inner_index) {
  478. case 0:
  479. loss_out = gold_side_b * (1 - rebate_side_b) + gold_side_c * (1 - rebate_side_c);
  480. inner_ref_value = gold_side_a;
  481. inner_odds = odds_side_a;
  482. break;
  483. case 1:
  484. loss_out = gold_side_a * (1 - rebate_side_a) + gold_side_c * (1 - rebate_side_c);
  485. inner_ref_value = gold_side_b;
  486. inner_odds = odds_side_b;
  487. break;
  488. case 2:
  489. const { loss_proportion_a, loss_proportion_b } = lossProportion(betInfo);
  490. loss_out = gold_side_a * loss_proportion_a + gold_side_b * loss_proportion_b;
  491. inner_ref_value = gold_side_c;
  492. inner_odds = odds_side_c;
  493. break;
  494. }
  495. return { loss_out, inner_ref_value, inner_odds };
  496. }
  497. /**
  498. * 结合第一关亏损计算第二关新利润
  499. */
  500. const calcTotalProfitWithFixedFirst = (betInfo1, betInfo2, inner_base, inner_rebate) => {
  501. const { loss_out, inner_ref_value, inner_odds } = getFirstInfo(betInfo1);
  502. if (inner_base && inner_base != inner_ref_value) {
  503. Logs.out('inner_base is not equal to inner_ref_value', inner_base, inner_ref_value);
  504. throw new Error('内盘基准额度和内盘索引额度不一致');
  505. }
  506. else if (!inner_base) {
  507. inner_base = inner_ref_value;
  508. }
  509. const profitInfo = calcSecondProfit({ ...betInfo2, inner_base, inner_odds_first: inner_odds, inner_rebate });
  510. const { cross_type } = profitInfo;
  511. profitInfo.win_side_a = typeof(profitInfo.win_side_a) !== 'number' ? undefined : fixFloat(profitInfo.win_side_a - loss_out);
  512. profitInfo.win_side_b = typeof(profitInfo.win_side_b) !== 'number' ? undefined : fixFloat(profitInfo.win_side_b - loss_out);
  513. profitInfo.win_side_c = cross_type == 'la_wa_rv' ? 0 : (typeof(profitInfo.win_side_c) !== 'number' ? undefined : fixFloat(profitInfo.win_side_c - loss_out));
  514. profitInfo.win_average = fixFloat(profitInfo.win_average - loss_out);
  515. const { win_average_rate, win_profit_rate, ...profitInfoRest } = profitInfo;
  516. return profitInfoRest;
  517. }
  518. module.exports = {
  519. calcTotalProfit,
  520. calcTotalProfitWithFixedFirst,
  521. getFirstInfo,
  522. };