Skip to content

Instantly share code, notes, and snippets.

@kangchihlun
Created September 25, 2021 21:43
Show Gist options
  • Save kangchihlun/b15d98b619223c2dc03ee0d7696fbd62 to your computer and use it in GitHub Desktop.
Save kangchihlun/b15d98b619223c2dc03ee0d7696fbd62 to your computer and use it in GitHub Desktop.
支撐壓力線計算-使用 Volume Profile 找過去一日一分鐘最大量區-10跳間隔
const okex_api = require('../../libs/okex-api')
const constant = require('../../libs/constants')
const request = require('request')
const numgrid = 100
var marketinfo = {}
const fetch_market_info = async () => {
let _mkt = await okex_api.fetch_perp_symbols(mode='all')
_mkt.forEach((inst) => {
marketinfo[inst.instrument_id] = inst
})
}
// 返回最小跳動單位 * n
const snap_min_tick_size_mult = (inst1,price,numTick) =>{
let tick_size = parseFloat(marketinfo[inst1].tick_size)
let tick_decimal = 0
let ticke_decimal_spl = marketinfo[inst1].tick_size.toString().split('.')
if(ticke_decimal_spl.length>1){
tick_decimal = ticke_decimal_spl[1].length
}
let mult = parseInt(price/tick_size)
return (mult*tick_size).toFixed(tick_decimal*numTick)
}
// price grouping
// 目前統一到 marketinfo 最小單位 * 10(10跳)
const snap_value_by_yd_grid = (symb,ydc,curval) => {
let single_sec = ydc / numgrid
let numsec_curval = parseInt(curval / single_sec)
return snap_min_tick_size(symb,numsec_curval*single_sec)
}
/**
* Volume Profile 過去一日一分鐘最大量區
*/
const fetch_candle_1M = async (symbol,since) => {
return new Promise((resolve,reject) => {
let requrl = `${okex_api.baseurl}/api/v5/market/history-candles?instId=${symbol}&bar=1m&after=${since}&limit=1440`
if(!(Number.isInteger(since))){
resolve(`end`)
}else{
request(requrl ,{ json: true }, async (err, res, body) => {
if (err) { return console.log(err) }
if(res.statusCode === 200){
resolve(res.body.data)
}
})
}
})
}
const collect_history_candles_1m = async (symbol) => {
return new Promise(async (resolve, reject)=>{
const day_1m_count = 1440
let collector = new Promise(async (resolve, reject)=>{
let now = Date.now()
let lastbartime = now
let allKLines = [];
(function loopIt() {
setTimeout(async()=>{
let kldata = await fetch_candle_1M(symbol,lastbartime-1)
if(allKLines.length > day_1m_count){
resolve(allKLines)
}else{
allKLines = allKLines.concat(kldata)
let _lasttime = parseInt(kldata[kldata.length-1])
lastbartime = _lasttime
loopIt()
}
}, 1000)
})()
})
collector.then((klines_1min_day) => {
let price_vol = {}
let numtick = 2
klines_1min_day.forEach((kline) => {
let vol = parseFloat(kline[5])
let price = ( parseFloat(kline[2]) + parseFloat(kline[3]) )*0.5
price = snap_min_tick_size_mult(symbol,price,numtick)
if(!(price in price_vol)){
price_vol[price] = {price,volume:vol}
}else{
price_vol[price][`volume`] += vol
}
})
klines_1min_day_sorted = Object.values(price_vol).sort(function(a,b){return b.volume - a.volume})
let gridlines = [
parseFloat(klines_1min_day_sorted[0].price) ,
parseFloat(klines_1min_day_sorted[1].price),
parseFloat(klines_1min_day_sorted[2].price),
parseFloat(klines_1min_day_sorted[3].price),
parseFloat(klines_1min_day_sorted[4].price),
]
resolve(gridlines)
})
})
}
const fetch_volume_profile_by_symbol = async (symbol) => {
await fetch_market_info()
return await collect_history_candles_1m(symbol)
}
/**
* 3分鐘k 21 ma
*/
const fetch_candle_3M = async (symbol,since,limit) => {
return new Promise((resolve,reject) => {
let requrl = `${okex_api.baseurl}/api/v5/market/history-candles?instId=${symbol}&bar=3m&after=${since}&limit=${limit}`
if(!(Number.isInteger(since))){
resolve(`end`)
}else{
request(requrl ,{ json: true }, async (err, res, body) => {
if (err) { return console.log(err) }
if(res.statusCode === 200){
resolve(res.body.data)
}
})
}
})
}
const getMean = (array) => {
const n = array.length
return array.reduce((a, b) => a + b) / n
}
const getStandardDeviation = (array) => {
const n = array.length
const mean = array.reduce((a, b) => a + b) / n
return Math.sqrt(array.map(x => Math.pow(x - mean, 2)).reduce((a, b) => a + b) / n)
}
const fetch_boll_3m = async (symbol) => {
const ma_count = 20
const numtick = 2
return new Promise(async (resolve, reject)=>{
let now = Date.now()
let kldata = await fetch_candle_3M(symbol,now,ma_count)
let closearr = kldata.map((kl) => parseFloat(kl[4]))
let std = getStandardDeviation(closearr)
let mean = getMean(closearr)
upband = snap_min_tick_size_mult(symbol,mean+std*2,numtick)
lowband = snap_min_tick_size_mult(symbol,mean-std*2,numtick)
resolve( [
parseFloat(upband),
parseFloat(lowband),
] )
})
}
/**
* 關卡價關鍵價
*/
const fetch_grids = async (symb) => {
let grids = await fetch_volume_profile_by_symbol(symb)
let bo_3m_20 = await fetch_boll_3m(symb)
grids = grids.concat(bo_3m_20)
grids_sorted = grids.sort((a,b) => {return (a-b)})
return grids_sorted
}
module.exports = {
fetch_volume_profile_by_symbol,
fetch_boll_3m,
fetch_grids,
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment