|
@@ -39,42 +39,55 @@ function statisticB(kLines, index) {
|
|
|
return count
|
|
return count
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/* 形态学说 */
|
|
|
|
|
|
|
+/* 指标学说 */
|
|
|
|
|
|
|
|
-// 如果前一根k线是阴线,并且收了影线,影线涨幅>=实体跌幅*0.732【有用,能过滤60%的交易,但是过滤的交易很多都是能盈利的,所以这个因子只能说保留一下】
|
|
|
|
|
-function statisticD(_kLines, _index) {
|
|
|
|
|
- // let k = kLines[index - 1]
|
|
|
|
|
- //
|
|
|
|
|
- // if (!k) return 0
|
|
|
|
|
- //
|
|
|
|
|
- // // 计算实体的跌幅
|
|
|
|
|
- // const bodyDecline = k.Open - k.Close;
|
|
|
|
|
- //
|
|
|
|
|
- // // 如果跌幅小于5%,不适用这个过滤
|
|
|
|
|
- // if (100 * (k.Low - k.Open) / k.Open > -10) return 1
|
|
|
|
|
- //
|
|
|
|
|
- // // 计算下影线的涨幅
|
|
|
|
|
- // const lowerShadowGain = Math.min(k.Open, k.Close) - k.Low;
|
|
|
|
|
- //
|
|
|
|
|
- // // 判断下影线的涨幅是否大于或等于实体的跌幅
|
|
|
|
|
- // const hasLongLowerShadow = (lowerShadowGain / k.Low) >= (bodyDecline / k.Open) * 1;
|
|
|
|
|
- //
|
|
|
|
|
- // // 阴线并且下影线涨幅大于或等于实体跌幅
|
|
|
|
|
- // return hasLongLowerShadow ? 1 : 0;
|
|
|
|
|
-
|
|
|
|
|
- return 0
|
|
|
|
|
|
|
+// 一个新的指标,前N根共有M根与BTC走势一致
|
|
|
|
|
+function statisticC(kLines, btcKLines, index) {
|
|
|
|
|
+ let count = 0
|
|
|
|
|
+ for (let i = index - 1; i >= index - 6; i--) {
|
|
|
|
|
+ let kLine = kLines[i]
|
|
|
|
|
+ let btcKLine = btcKLines[i]
|
|
|
|
|
+
|
|
|
|
|
+ if (!kLines[i - 1] || !btcKLines[i - 1]) break
|
|
|
|
|
+
|
|
|
|
|
+ if (kLine.Open > kLine.Close && btcKLine.Open > btcKLine.Close) count += 1
|
|
|
|
|
+ if (kLine.Open < kLine.Close && btcKLine.Open < btcKLine.Close) count += 1
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return count
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-// 现在应该想一个形态,能过滤一下熊市时的亏损,牛市时的回撤无所谓
|
|
|
|
|
-// function statisticC(kLines, index) {
|
|
|
|
|
|
|
+/* 形态学说 */
|
|
|
|
|
+
|
|
|
|
|
+// 如果前一根k线是阴线,并且收了影线,影线涨幅>=实体跌幅*0.732【有用,能过滤60%的交易,但是过滤的交易很多都是能盈利的,所以这个因子只能说保留一下】
|
|
|
|
|
+// function statisticD(_kLines, _index) {
|
|
|
|
|
+// let k = kLines[index - 1]
|
|
|
|
|
+//
|
|
|
|
|
+// if (!k) return 0
|
|
|
|
|
+//
|
|
|
|
|
+// // 计算实体的跌幅
|
|
|
|
|
+// const bodyDecline = k.Open - k.Close;
|
|
|
|
|
+//
|
|
|
|
|
+// // 如果跌幅小于5%,不适用这个过滤
|
|
|
|
|
+// if (100 * (k.Low - k.Open) / k.Open > -10) return 1
|
|
|
|
|
+//
|
|
|
|
|
+// // 计算下影线的涨幅
|
|
|
|
|
+// const lowerShadowGain = Math.min(k.Open, k.Close) - k.Low;
|
|
|
//
|
|
//
|
|
|
|
|
+// // 判断下影线的涨幅是否大于或等于实体的跌幅
|
|
|
|
|
+// const hasLongLowerShadow = (lowerShadowGain / k.Low) >= (bodyDecline / k.Open) * 1;
|
|
|
|
|
+//
|
|
|
|
|
+// // 阴线并且下影线涨幅大于或等于实体跌幅
|
|
|
|
|
+// return hasLongLowerShadow ? 1 : 0;
|
|
|
|
|
+//
|
|
|
|
|
+// return 0
|
|
|
// }
|
|
// }
|
|
|
|
|
|
|
|
// 指标过滤
|
|
// 指标过滤
|
|
|
-function filter(kLines, index) {
|
|
|
|
|
|
|
+function filter(btcKLines, kLines, index) {
|
|
|
// 过去N根K的累计涨幅
|
|
// 过去N根K的累计涨幅
|
|
|
let upRateN = statisticA(kLines, index)
|
|
let upRateN = statisticA(kLines, index)
|
|
|
- if (upRateN <= 75 || upRateN >= 90) {
|
|
|
|
|
|
|
+ if (upRateN <= 80 || upRateN >= 90) {
|
|
|
return false
|
|
return false
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -83,11 +96,16 @@ function filter(kLines, index) {
|
|
|
return false
|
|
return false
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // 过去N根k线一共有M根与btc走势一致
|
|
|
|
|
+ if (statisticC(btcKLines, kLines, index) < 2) {
|
|
|
|
|
+ return false
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return true
|
|
return true
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
let realCountMap = {}
|
|
let realCountMap = {}
|
|
|
-function getRealDragonMap(kLinesMap, dayCount, BUY_LIMIT_RATE) {
|
|
|
|
|
|
|
+function getRealDragonMap(btcKLines, kLinesMap, dayCount, BUY_LIMIT_RATE) {
|
|
|
let realDragonMap = {}
|
|
let realDragonMap = {}
|
|
|
for (let symbol in kLinesMap) {
|
|
for (let symbol in kLinesMap) {
|
|
|
let kLines = kLinesMap[symbol]
|
|
let kLines = kLinesMap[symbol]
|
|
@@ -100,7 +118,7 @@ function getRealDragonMap(kLinesMap, dayCount, BUY_LIMIT_RATE) {
|
|
|
if (!kLine || !prevKline) continue
|
|
if (!kLine || !prevKline) continue
|
|
|
|
|
|
|
|
// 指标过滤
|
|
// 指标过滤
|
|
|
- if (!filter(kLines, index)) continue
|
|
|
|
|
|
|
+ if (!filter(btcKLines, kLines, index)) continue
|
|
|
|
|
|
|
|
let rate = 100 * (kLine.Close - kLine.Open) / kLine.Open
|
|
let rate = 100 * (kLine.Close - kLine.Open) / kLine.Open
|
|
|
// let upRate = 100 * (kLine.High - kLine.Open) / kLine.Open
|
|
// let upRate = 100 * (kLine.High - kLine.Open) / kLine.Open
|
|
@@ -126,7 +144,7 @@ function getRealDragonMap(kLinesMap, dayCount, BUY_LIMIT_RATE) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
let fakeCountMap = {}
|
|
let fakeCountMap = {}
|
|
|
-function getFakeDragonMap(kLinesMap, dayCount, BUY_LIMIT_RATE) {
|
|
|
|
|
|
|
+function getFakeDragonMap(btcKLines, kLinesMap, dayCount, BUY_LIMIT_RATE) {
|
|
|
let fakeDragonMap = {}
|
|
let fakeDragonMap = {}
|
|
|
for (let symbol in kLinesMap) {
|
|
for (let symbol in kLinesMap) {
|
|
|
let kLines = kLinesMap[symbol]
|
|
let kLines = kLinesMap[symbol]
|
|
@@ -138,7 +156,7 @@ function getFakeDragonMap(kLinesMap, dayCount, BUY_LIMIT_RATE) {
|
|
|
if (!kLine || (!prevKline)) continue
|
|
if (!kLine || (!prevKline)) continue
|
|
|
|
|
|
|
|
// 指标过滤
|
|
// 指标过滤
|
|
|
- if (!filter(kLines, index)) continue
|
|
|
|
|
|
|
+ if (!filter(btcKLines, kLines, index)) continue
|
|
|
|
|
|
|
|
let rate = 100 * (kLine.Close - kLine.Open) / kLine.Open
|
|
let rate = 100 * (kLine.Close - kLine.Open) / kLine.Open
|
|
|
if (rate < BUY_LIMIT_RATE) {
|
|
if (rate < BUY_LIMIT_RATE) {
|
|
@@ -163,47 +181,50 @@ let dataLeft = []
|
|
|
let dataRight = []
|
|
let dataRight = []
|
|
|
let tempLeft = []
|
|
let tempLeft = []
|
|
|
let tempRight = []
|
|
let tempRight = []
|
|
|
-let dataY = [...Array(200).keys()]
|
|
|
|
|
|
|
+let dataY = [...Array(40).keys()]
|
|
|
function dragonAnalysis(btcKLines, kLinesMap, dragonMap, dayCount) {
|
|
function dragonAnalysis(btcKLines, kLinesMap, dragonMap, dayCount) {
|
|
|
for (let symbol in dragonMap) {
|
|
for (let symbol in dragonMap) {
|
|
|
let kLines = kLinesMap[symbol]
|
|
let kLines = kLinesMap[symbol]
|
|
|
let index = kLines.length - (dayCount + 1)
|
|
let index = kLines.length - (dayCount + 1)
|
|
|
|
|
|
|
|
- let x = statisticB(kLines, index)
|
|
|
|
|
|
|
+ // let x = statisticB(kLines, index)
|
|
|
|
|
+ let x = statisticC(btcKLines, kLines, index)
|
|
|
let y = dragonMap[symbol].Profit
|
|
let y = dragonMap[symbol].Profit
|
|
|
|
|
|
|
|
// 打印实际的量
|
|
// 打印实际的量
|
|
|
- // if (y > 0) {
|
|
|
|
|
- // if (dataRight[x]) {
|
|
|
|
|
- // dataRight[x] += y
|
|
|
|
|
- // } else {
|
|
|
|
|
- // dataRight[x] = y
|
|
|
|
|
- // }
|
|
|
|
|
- // } else {
|
|
|
|
|
- // if (dataLeft[x]) {
|
|
|
|
|
- // dataLeft[x] += y
|
|
|
|
|
- // } else {
|
|
|
|
|
- // dataLeft[x] = y
|
|
|
|
|
- // }
|
|
|
|
|
- // }
|
|
|
|
|
-
|
|
|
|
|
- // 打印倍数
|
|
|
|
|
- if (y > 0) {
|
|
|
|
|
- if (tempRight[x]) {
|
|
|
|
|
- tempRight[x] += y
|
|
|
|
|
|
|
+ if (1 === 2) {
|
|
|
|
|
+ if (y > 0) {
|
|
|
|
|
+ if (dataRight[x]) {
|
|
|
|
|
+ dataRight[x] += y
|
|
|
|
|
+ } else {
|
|
|
|
|
+ dataRight[x] = y
|
|
|
|
|
+ }
|
|
|
} else {
|
|
} else {
|
|
|
- tempRight[x] = y
|
|
|
|
|
|
|
+ if (dataLeft[x]) {
|
|
|
|
|
+ dataLeft[x] += y
|
|
|
|
|
+ } else {
|
|
|
|
|
+ dataLeft[x] = y
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
- if (tempLeft[x]) {
|
|
|
|
|
- tempLeft[x] += y
|
|
|
|
|
|
|
+ // 打印倍数
|
|
|
|
|
+ if (y > 0) {
|
|
|
|
|
+ if (tempRight[x]) {
|
|
|
|
|
+ tempRight[x] += y
|
|
|
|
|
+ } else {
|
|
|
|
|
+ tempRight[x] = y
|
|
|
|
|
+ }
|
|
|
} else {
|
|
} else {
|
|
|
- tempLeft[x] = y
|
|
|
|
|
|
|
+ if (tempLeft[x]) {
|
|
|
|
|
+ tempLeft[x] += y
|
|
|
|
|
+ } else {
|
|
|
|
|
+ tempLeft[x] = y
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
+ dataRight[x] = (tempLeft[x]?tempRight[x]/Math.abs(tempLeft[x]):0)
|
|
|
|
|
+ if (dataRight[x] > 10) dataRight[x] = 10
|
|
|
|
|
+ if (dataRight[x] < 0.5) dataRight[x] = 0.5
|
|
|
}
|
|
}
|
|
|
- dataRight[x] = (tempLeft[x]?tempRight[x]/Math.abs(tempLeft[x]):0)
|
|
|
|
|
- if (dataRight[x] > 10) dataRight[x] = 10
|
|
|
|
|
- if (dataRight[x] < 0.5) dataRight[x] = 0.5
|
|
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -212,7 +233,7 @@ async function main() {
|
|
|
|
|
|
|
|
const BUY_LIMIT_RATE = 0 // 从什么比例入场
|
|
const BUY_LIMIT_RATE = 0 // 从什么比例入场
|
|
|
const FIRST_FEW_DAYS = 1 // 第几K的数据,0表示今K,1表示昨K,2表示前K,以此类推
|
|
const FIRST_FEW_DAYS = 1 // 第几K的数据,0表示今K,1表示昨K,2表示前K,以此类推
|
|
|
- const BAKE_TEST_DAYS = 800 // 一共回测多少K
|
|
|
|
|
|
|
+ const BAKE_TEST_DAYS = 900 // 一共回测多少K
|
|
|
// const FIRST_FEW_DAYS = 710 // 第几K的数据,0表示今K,1表示昨K,2表示前K,以此类推
|
|
// const FIRST_FEW_DAYS = 710 // 第几K的数据,0表示今K,1表示昨K,2表示前K,以此类推
|
|
|
// const BAKE_TEST_DAYS = 1 // 一共回测多少K
|
|
// const BAKE_TEST_DAYS = 1 // 一共回测多少K
|
|
|
|
|
|
|
@@ -226,7 +247,7 @@ async function main() {
|
|
|
// 赚钱榜
|
|
// 赚钱榜
|
|
|
// logger.info("----------------赚钱榜数据分析----------------")
|
|
// logger.info("----------------赚钱榜数据分析----------------")
|
|
|
let realDragonProfit = 0
|
|
let realDragonProfit = 0
|
|
|
- let realDragonMap = getRealDragonMap(kLinesMap, day_count, BUY_LIMIT_RATE)
|
|
|
|
|
|
|
+ let realDragonMap = getRealDragonMap(btcKLines, kLinesMap, day_count, BUY_LIMIT_RATE)
|
|
|
for (let symbol in realDragonMap) {
|
|
for (let symbol in realDragonMap) {
|
|
|
realDragonProfit += realDragonMap[symbol].Profit
|
|
realDragonProfit += realDragonMap[symbol].Profit
|
|
|
// logger.info(`${realDragonMap[symbol].Symbol}, ${realDragonMap[symbol].Profit}%`)
|
|
// logger.info(`${realDragonMap[symbol].Symbol}, ${realDragonMap[symbol].Profit}%`)
|
|
@@ -236,7 +257,7 @@ async function main() {
|
|
|
// logger.info("----------------亏钱榜数据分析----------------")
|
|
// logger.info("----------------亏钱榜数据分析----------------")
|
|
|
// 亏钱榜
|
|
// 亏钱榜
|
|
|
let fakeDragonProfit = 0
|
|
let fakeDragonProfit = 0
|
|
|
- let fakeDragonMap = getFakeDragonMap(kLinesMap, day_count, BUY_LIMIT_RATE)
|
|
|
|
|
|
|
+ let fakeDragonMap = getFakeDragonMap(btcKLines, kLinesMap, day_count, BUY_LIMIT_RATE)
|
|
|
for (let symbol in fakeDragonMap) {
|
|
for (let symbol in fakeDragonMap) {
|
|
|
fakeDragonProfit += fakeDragonMap[symbol].Profit
|
|
fakeDragonProfit += fakeDragonMap[symbol].Profit
|
|
|
// logger.info(`${fakeDragonMap[symbol].Symbol}, ${fakeDragonMap[symbol].Profit}%`)
|
|
// logger.info(`${fakeDragonMap[symbol].Symbol}, ${fakeDragonMap[symbol].Profit}%`)
|