十面埋伏分析.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. const logger = require("./utils/logger");
  2. const NumKit = require('./utils/num-kit')
  3. const TimeKit = require('./utils/time-kit')
  4. const fs = require('fs').promises;
  5. async function readData() {
  6. let data = await fs.readFile('./data/k_lines.json', 'utf8')
  7. return JSON.parse(data)
  8. }
  9. let realCountMap = {}
  10. function getRealDragonMap(kLinesMap, FIRST_FEW_DAYS, BUY_LIMIT_RATE) {
  11. let realDragonMap = {}
  12. for (let symbol in kLinesMap) {
  13. let kLines = kLinesMap[symbol]
  14. let index = kLines.length - (FIRST_FEW_DAYS + 1)
  15. let kLine = kLines[index]
  16. let prevKline = kLines[index - 1]
  17. // 开盘第一天不计算
  18. if (!kLine || !prevKline) continue
  19. let rate = 100 * (kLine.Close - kLine.Open) / kLine.Open
  20. if (rate > BUY_LIMIT_RATE) {
  21. kLine.Rate = rate
  22. kLine.Profit = rate - BUY_LIMIT_RATE
  23. realDragonMap[symbol] = kLine
  24. if (!realCountMap[symbol]) {
  25. realCountMap[symbol] = 1
  26. } else {
  27. realCountMap[symbol] += 1
  28. }
  29. }
  30. }
  31. return realDragonMap
  32. }
  33. let fakeCountMap = {}
  34. function getFakeDragonMap(kLinesMap, FIRST_FEW_DAYS, BUY_LIMIT_RATE) {
  35. let fakeDragonMap = {}
  36. for (let symbol in kLinesMap) {
  37. let kLines = kLinesMap[symbol]
  38. let index = kLines.length - (FIRST_FEW_DAYS + 1)
  39. let kLine = kLines[index]
  40. let prevKline = kLines[index - 1]
  41. // 开盘第一天不计算
  42. if (!kLine || (!prevKline)) continue
  43. let rate = 100 * (kLine.Close - kLine.Open) / kLine.Open
  44. let maxRate = 100 * (kLine.High - kLine.Open) / kLine.Open
  45. if (maxRate > BUY_LIMIT_RATE && rate < BUY_LIMIT_RATE) {
  46. kLine.Rate = rate
  47. kLine.MaxRate = maxRate
  48. kLine.Profit = rate > 0 ? rate - BUY_LIMIT_RATE : -BUY_LIMIT_RATE
  49. fakeDragonMap[symbol] = kLine
  50. if (!fakeCountMap[symbol]) {
  51. fakeCountMap[symbol] = 1
  52. } else {
  53. fakeCountMap[symbol] += 1
  54. }
  55. }
  56. }
  57. return fakeDragonMap
  58. }
  59. async function main() {
  60. let kLinesMap = await readData()
  61. const FIRST_FEW_DAYS = 1 // 第几天的数据,0表示今天,1表示昨天,2表示前天,以此类推
  62. const BUY_LIMIT_RATE = 2.5 // 从什么比例入场
  63. const BAKE_TEST_DAYS = 150 // 一共回测多少天
  64. let totalProfit = 0
  65. for (let i = FIRST_FEW_DAYS; i < BAKE_TEST_DAYS; i++) {
  66. // 真龙榜
  67. let realDragonProfit = 0
  68. let realDragonMap = getRealDragonMap(kLinesMap, i, BUY_LIMIT_RATE)
  69. for (let symbol in realDragonMap) {
  70. realDragonProfit += realDragonMap[symbol].Profit
  71. // logger.info(realDragonMap[symbol].Symbol, realDragonMap[symbol].Profit, realDragonMap[symbol].Rate)
  72. }
  73. // logger.info("----------------真龙榜数据定量分析----------------")
  74. // dragonAnalysis(realDragonMap)
  75. // 假龙榜
  76. let fakeDragonProfit = 0
  77. let fakeDragonMap = getFakeDragonMap(kLinesMap, i, BUY_LIMIT_RATE)
  78. for (let symbol in fakeDragonMap) {
  79. fakeDragonProfit += fakeDragonMap[symbol].Profit
  80. // logger.info(fakeDragonMap[symbol].Symbol, fakeDragonMap[symbol].Profit, fakeDragonMap[symbol].MaxRate, fakeDragonMap[symbol].Rate)
  81. }
  82. // logger.info("----------------假龙榜数据定量分析----------------")
  83. // dragonAnalysis(fakeDragonMap, fakeCountMap)
  84. realDragonProfit = NumKit.getSubFloat(realDragonProfit, 2)
  85. fakeDragonProfit = NumKit.getSubFloat(fakeDragonProfit, 2)
  86. let realLength = Object.keys(realDragonMap).length
  87. let fakeLength = Object.keys(fakeDragonMap).length
  88. let realRate = NumKit.getSubFloat(realLength / (realLength + fakeLength), 2)
  89. let fakeRate = NumKit.getSubFloat(1 - realRate, 2)
  90. let expRealProfit = NumKit.getSubFloat(realRate * realDragonProfit, 2)
  91. let expFakeProfit = NumKit.getSubFloat(fakeRate * fakeDragonProfit, 2)
  92. let synProfit = NumKit.getSubFloat(expFakeProfit + expRealProfit, 2)
  93. let avgProfit = NumKit.getSubFloat(synProfit / (realLength + fakeLength), 2)
  94. let index = kLinesMap['BTC_USDT'].length - (i + 1)
  95. let btcK = kLinesMap['BTC_USDT'][index]
  96. let dateStr = TimeKit.getDateByMillisecond(btcK.Time)
  97. let btcUpRate = NumKit.getSubFloat(100 * (btcK.Close - btcK.Open) / btcK.Open, 2)
  98. logger.info(`${i}日(${dateStr}, ${realLength + fakeLength}只),真龙榜(${realLength}只)利润${realDragonProfit}%`
  99. + `,假龙榜(${fakeLength}只)利润${fakeDragonProfit}%`
  100. + `,真龙期望利润${expRealProfit}%,假龙期望利润${expFakeProfit}%,综合利润${synProfit}%,平均每只利润${avgProfit}%,BTC涨幅${btcUpRate}%`
  101. )
  102. totalProfit += avgProfit
  103. totalProfit = NumKit.getSubFloat(totalProfit, 2)
  104. }
  105. let dayProfit = NumKit.getSubFloat(totalProfit / BAKE_TEST_DAYS, 2)
  106. logger.info(`利润期望值总和:${totalProfit}%,平均日化${dayProfit}%。`)
  107. for (let symbol in fakeCountMap) {
  108. logger.info(`${symbol} 真${realCountMap[symbol]},假${fakeCountMap[symbol]}`)
  109. }
  110. }
  111. main().catch((error) => {
  112. logger.error(error.stack);
  113. process.exitCode = 1;
  114. })