Skip to content

Instantly share code, notes, and snippets.

@treypeng
Last active March 18, 2019 07:53
Show Gist options
  • Save treypeng/a9141c2b293c52dfe366c1134f5bc55d to your computer and use it in GitHub Desktop.
Save treypeng/a9141c2b293c52dfe366c1134f5bc55d to your computer and use it in GitHub Desktop.
Script to detect darth maul candles from bitmex 1h interval data
require('./util');
const Candler = require('./candle-db');
const ATR_LENGTH = 24;
const SMA_LENGTH = 24;
let trs = []; // series. needed by atr() function.
// Open the database, cut down version to save size, contains only 2019 1h candle data
let candler = new Candler('./bitmex-xbt-1h-2019-only.db');
// Get H1 xbtusd candles from 2019 year open
let candles = candler.get_range('bitmex', '1h', 'btcusd', date(2019,1,1), Date.now());
// Go through each of the candles, starting from the first one at 00:00 on 1st January 2019
for (let i=0; i < candles.length; i++)
{
// Current ATR for this candle
let a = atr( candles, i, ATR_LENGTH );
// Let's also compute the SMA(24) of the close price:
let s = sma ( (candles.slice(0, i + 1)).map ( e => e.close ), SMA_LENGTH );
// uncomment this line to see the atr and sma for this H1 candle:
// console.log(`atr = ${a}, sma = ${s} timestamp = ${strdate(candles[i].timestamp)}`);
let dm = is_darth_maul( candles[i], a, s );
if (dm)
{
console.log(`\n🚨 The Sith will rule the galaxy: ${strdate(candles[i].timestamp)}`);
console.log( candles[i] );
}
}
function is_darth_maul(candle, current_atr, current_sma)
{
const DARTH_MAUL_RANGE = 1.0; // wicks that are +100% outside the ATR band's range
// The way this works is we compute an ATR 'band' using the SMA of the close
// price and the ATR of the current candle
let atr_upper_band = current_sma + current_atr;
let atr_lower_band = current_sma - current_atr;
let band_range = atr_upper_band - atr_lower_band;
// Now we see by how much (if at all) the wicks extended through the band's range
let upper_wick_dev = candle.high - atr_upper_band;
let lower_wick_dev = atr_lower_band - candle.low;
// if either wick inside the band, it's definitely not a Darth Maul, return
if (upper_wick_dev < 0 || lower_wick_dev < 0)
return false;
// Ok, they both exceeded the band, but by what factor?
let upper_factor = upper_wick_dev / band_range;
let lower_factor = lower_wick_dev / band_range;
// Make sure they both did, upside or downside only doesn't count
if (upper_factor >= DARTH_MAUL_RANGE && lower_factor >= DARTH_MAUL_RANGE)
return true;
return false;
}
// Function to compute ATR
function atr(candles, index, length)
{
// Get the current candle
let candle0 = candles[index];
// Get the previous candle
let candle1 = (index >= 0) ? candles[index-1] : null;
// not sure if I need to do this or can use candle0 alone :thonking:
if (!candle1) return;
// First, let's calculate the True Range, from the PineScript documentation:
// max(high - low, abs(high - close[1]), abs(low - close[1]))
let tr = Math.max( candle0.high - candle0.low,
Math.max(
Math.abs(candle0.high - candle1.close),
Math.abs(candle0.low - candle1.close)
)
);
// Save our ongoing series of True Ranges
trs.push(tr)
// Now return the simple-moving-average of them (see util.js):
return sma( trs, length );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment