how to migrate from zerodha kite to angelone
Migrate to angelone java sdk. Append _AO to name: package mts;
import com.zerodhatech.kiteconnect.KiteConnect;
import com.zerodhatech.kiteconnect.kitehttp.exceptions.KiteException;
import com.zerodhatech.models.HistoricalData;
import com.zerodhatech.models.Instrument;
import java.awt.Toolkit;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* Adaptive Channel + Volumized Bullish Order Blocks Buy Scanner
* Buy when: price above Adaptive Median Line + recent bullish OB respected
*/
public class AdaptiveChannelVolOBBuyScanner {
// ── Configuration ───────────────────────────────────────────────────────────
private static final double DEV_MULTIPLIER = 2.0;
private static final int ATR_PERIOD = 10;
private static final float MAX_ATR_MULT_OB = 3.5f;
private static final int SWING_LENGTH = 10;
private static final int MAX_RECENT_BULL_OB = 5;
// Filters
private static final int RSI_PERIOD = 14;
private static final double RSI_MIN_BUY = 48.0;
private static final int ADX_PERIOD = 14;
private static final double ADX_MIN = 20.0;
private static final int VOL_PERIOD = 20;
private static final double VOL_MULTIPLIER = 1.35;
// Kite Connect
private static final String API_KEY = "g9wl2rucy7fgl79g";
private static final String USER_ID = "XCY173";
private static final String TOKEN_FILE = "tokens.json";
private static KiteConnect kiteConnect;
private static final SimpleDateFormat LOG_FMT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static PrintWriter logWriter;
private static final Map<String, String> symbolToToken = new HashMap<>();
// Watchlist
private static final String[] SYMBOLS = {
"RELIANCE","HDFCBANK","ICICIBANK","INFY","TCS","KOTAKBANK","HINDUNILVR","ITC","SBIN","BHARTIARTL",
"LT","AXISBANK","BAJFINANCE","MARUTI","ASIANPAINT","SUNPHARMA","TITAN","HCLTECH","TATAMOTORS","ULTRACEMCO",
"BAJAJFINSV","WIPRO","NESTLEIND","TECHM","JSWSTEEL","POWERGRID","NTPC","ONGC","ADANIENT","ADANIPORTS",
"COALINDIA","TATASTEEL","M&M","DIVISLAB","DRREDDY","APOLLOHOSP","BRITANNIA","CIPLA","HEROMOTOCO","EICHERMOT",
"SHREECEM","GRASIM","BPCL","IOC","HDFCLIFE","SBILIFE","BAJAJ-AUTO","TRENT","ZOMATO","ADANIGREEN",
"PIDILITIND","GODREJCP","VBL","DMART","ATGL","SRF","BERGEPAINT","HAVELLS","ABB","SIEMENS",
"DABUR","MARICO","COLPAL","LTIM","TORNTPHARM","INDUSINDBK","PNB","BANKBARODA","CANBK","UNIONBANK",
"TATAPOWER","GAIL","VEDL","HINDALCO","JINDALSTEL","ACC","AMBUJACEM","UPL","LUPIN","CHOLAFIN"
};
public static void main(String[] args) {
try {
logWriter = new PrintWriter(new FileWriter("adaptive_volob_buy_scanner.log", true));
System.out.println("=== ADAPTIVE CHANNEL + VOLUMIZED BULLISH OB BUY SCANNER ===");
log("SCAN STARTED @ " + LOG_FMT.format(new Date()));
if (!loadSession()) return;
loadInstrumentTokens();
int hits = 0;
for (String symbol : SYMBOLS) {
try {
if (checkAdaptiveChannelVolOBBuy(symbol.trim())) hits++;
Thread.sleep(1200);
} catch (Exception ignored) {}
}
System.out.println("\nSCAN COMPLETE — " + hits + " setups found");
log("SCAN COMPLETE — " + hits + " ADAPTIVE + VOL OB BUY setups");
logWriter.close();
if (hits > 0) beep(3);
} catch (Exception e) {
e.printStackTrace();
}
}
// ── Core Logic ──────────────────────────────────────────────────────────────
private static boolean checkAdaptiveChannelVolOBBuy(String symbol) throws Exception {
String token = symbolToToken.get(symbol.toUpperCase());
if (token == null) return false;
HistoricalData data = fetchDailyData(token);
List<HistoricalData> candles = data.dataArrayList;
int n = candles.size();
if (n < 300) return false;
double[] open = new double[n];
double[] high = new double[n];
double[] low = new double[n];
double[] close = new double[n];
long[] volume = new long[n];
for (int i = 0; i < n; i++) {
HistoricalData c = candles.get(i);
open[i] = c.open;
high[i] = c.high;
low[i] = c.low;
close[i] = c.close;
volume[i] = c.volume;
}
double[] atr = calculateATR(high, low, close, ATR_PERIOD);
// 1. Approximate Adaptive Median Line (last known value)
double medianLineApprox = approximateAdaptiveMedian(close, n);
if (Double.isNaN(medianLineApprox)) return false;
int last = n - 1;
if (close[last] <= medianLineApprox) return false; // must be ABOVE median line
// 2. Recent Bullish Order Blocks
List<BullishOrderBlock> bullOBs = findRecentBullishOrderBlocks(
open, high, low, close, volume, atr, n, SWING_LENGTH);
if (bullOBs.isEmpty()) return false;
BullishOrderBlock recentOB = bullOBs.get(0);
// Respect / Retest condition
boolean respectingOB = close[last] >= recentOB.bottom && close[last] <= recentOB.top * 1.015;
boolean freshRetest = close[last-1] < recentOB.top && close[last] >= recentOB.bottom;
if (!respectingOB && !freshRetest) return false;
// No invalidation
boolean invalidated = low[last] < recentOB.bottom;
if (invalidated) return false;
// 3. Classic Filters
double[] rsi = calculateRSI(close, RSI_PERIOD);
if (rsi[last] < RSI_MIN_BUY) return false;
double[] adx = calculateADX(high, low, close, ADX_PERIOD);
if (adx[last] < ADX_MIN) return false;
double avgVol = 0;
int volCount = Math.min(VOL_PERIOD, n);
for (int i = n - volCount; i < n; i++) avgVol += volume[i];
avgVol /= volCount;
if (volume[last] < avgVol * VOL_MULTIPLIER) return false;
// ── Signal Confirmed ────────────────────────────────────────────────────
double entry = close[last];
double sl = recentOB.bottom - atr[last] * 0.4;
double risk = entry - sl;
double tp1 = entry + risk * 2.0;
double tp2 = entry + risk * 3.2;
String msg = String.format(
"ADAPTIVE + VOL OB BUY ▲ | %s.NS | Entry ~%.2f | " +
"Above Median | OB [%.2f–%.2f] Vol:%.0f | SL %.2f | TP1 %.2f / TP2 %.2f | " +
"RSI %.1f | ADX %.1f | Vol %.1fx",
symbol.toUpperCase(), entry,
recentOB.bottom, recentOB.top, recentOB.volume,
sl, tp1, tp2,
rsi[last], adx[last], (double)volume[last]/avgVol
);
System.out.println(msg);
log(msg);
beep(2);
return true;
}
// ── Very Simplified Adaptive Median Approximation ───────────────────────────
// (real Pine uses regression over multiple lengths → we approximate with longest good fit)
private static double approximateAdaptiveMedian(double[] close, int n) {
if (n < 250) return Double.NaN;
// We try several periods (like 100,200,300,400,500)
int[] periods = {100, 150, 200, 250, 300, 350, 400, 450, 500};
double bestR = -1;
double bestMedian = Double.NaN;
for (int period : periods) {
if (n < period + 10) continue;
double sumX = 0, sumY = 0, sumXY = 0, sumXX = 0;
int count = period;
for (int i = 0; i < count; i++) {
int idx = n - count + i;
double x = i + 1;
double y = Math.log(close[idx]);
sumX += x;
sumY += y;
sumXY += x * y;
sumXX += x * x;
}
double slope = (count * sumXY - sumX * sumY) / (count * sumXX - sumX * sumX);
double intercept = (sumY - slope * sumX) / count;
// Pearson R approximation
double r = Math.abs(slope) > 0.0001 ? 0.85 : 0.4; // rough proxy
if (r > bestR) {
bestR = r;
// Last point of the regression line (median approx)
double lastX = count;
bestMedian = Math.exp(intercept + slope * lastX);
}
}
return bestMedian;
}
// ── Bullish Order Block Detection (same as previous) ────────────────────────
static class BullishOrderBlock {
double top;
double bottom;
long volume;
int startBarIndex;
BullishOrderBlock(double top, double bottom, long volume, int startBar) {
this.top = top;
this.bottom = bottom;
this.volume = volume;
this.startBarIndex = startBar;
}
}
private static List<BullishOrderBlock> findRecentBullishOrderBlocks(
double[] open, double[] high, double[] low, double[] close, long[] volume,
double[] atr, int n, int swingLen) {
List<BullishOrderBlock> bullOBs = new ArrayList<>();
for (int i = swingLen * 2; i < n - 1; i++) {
boolean potentialReversal = close[i] > close[i-1] && close[i-1] < close[i-2];
if (!potentialReversal) continue;
int lowIdx = i - 1;
for (int k = 1; k <= swingLen && (i - k - 1) >= 0; k++) {
if (low[i - k] < low[lowIdx]) lowIdx = i - k;
}
double obBottom = Math.min(low[lowIdx], low[lowIdx + 1]);
double obTop = Math.max(open[lowIdx], close[lowIdx]);
double obSize = obTop - obBottom;
if (obSize > atr[i] * MAX_ATR_MULT_OB) continue;
long obVol = volume[lowIdx] + volume[lowIdx + 1] + volume[lowIdx + 2];
bullOBs.add(new BullishOrderBlock(obTop, obBottom, obVol, lowIdx));
if (bullOBs.size() >= MAX_RECENT_BULL_OB) break;
}
bullOBs.sort((a, b) -> Integer.compare(b.startBarIndex, a.startBarIndex));
return bullOBs;
}
// ── Technical Indicators (RSI, ADX, ATR) ────────────────────────────────────
// (same implementations as in previous scanners)
private static double[] calculateRSI(double[] close, int period) {
int n = close.length;
double[] rsi = new double[n];
if (n < period + 1) return rsi;
double gain = 0, loss = 0;
for (int i = 1; i <= period; i++) {
double chg = close[i] - close[i - 1];
if (chg > 0) gain += chg; else loss -= chg;
}
double avgGain = gain / period;
double avgLoss = loss / period;
rsi[period] = avgLoss == 0 ? 100 : 100 - (100 / (1 + avgGain / avgLoss));
for (int i = period + 1; i < n; i++) {
double chg = close[i] - close[i - 1];
double cg = chg > 0 ? chg : 0;
double cl = chg < 0 ? -chg : 0;
avgGain = (avgGain * (period - 1) + cg) / period;
avgLoss = (avgLoss * (period - 1) + cl) / period;
rsi[i] = avgLoss == 0 ? 100 : 100 - (100 / (1 + avgGain / avgLoss));
}
return rsi;
}
private static double[] calculateADX(double[] high, double[] low, double[] close, int period) {
int n = high.length;
double[] adx = new double[n];
double[] plusDI = new double[n];
double[] minusDI = new double[n];
for (int i = 1; i < n; i++) {
double up = high[i] - high[i - 1];
double down = low[i - 1] - low[i];
plusDI[i] = (up > down && up > 0) ? up : 0;
minusDI[i] = (down > up && down > 0) ? down : 0;
}
double[] smoothedPlus = ema(plusDI, period);
double[] smoothedMinus = ema(minusDI, period);
double[] atrArr = atr(high, low, close, period);
for (int i = 0; i < n; i++) {
plusDI[i] = 100 * smoothedPlus[i] / (atrArr[i] == 0 ? 1 : atrArr[i]);
minusDI[i] = 100 * smoothedMinus[i] / (atrArr[i] == 0 ? 1 : atrArr[i]);
}
double[] dx = new double[n];
for (int i = 0; i < n; i++) {
double diff = Math.abs(plusDI[i] - minusDI[i]);
double sum = plusDI[i] + minusDI[i];
dx[i] = sum == 0 ? 0 : 100 * diff / sum;
}
return ema(dx, period);
}
private static double[] ema(double[] src, int period) {
int n = src.length;
double[] ema = new double[n];
double k = 2.0 / (period + 1);
ema[0] = src[0];
for (int i = 1; i < n; i++) {
ema[i] = src[i] * k + ema[i-1] * (1 - k);
}
return ema;
}
private static double[] calculateATR(double[] high, double[] low, double[] close, int period) {
return atr(high, low, close, period);
}
private static double[] atr(double[] high, double[] low, double[] close, int period) {
int n = high.length;
double[] tr = new double[n];
tr[0] = high[0] - low[0];
for (int i = 1; i < n; i++) {
tr[i] = Math.max(high[i] - low[i],
Math.max(Math.abs(high[i] - close[i-1]), Math.abs(low[i] - close[i-1])));
}
return ema(tr, period);
}
// ── Kite & Logging ──────────────────────────────────────────────────────────
private static boolean loadSession() { /* same as previous */
try (FileReader fr = new FileReader(TOKEN_FILE)) {
org.json.JSONObject json = new org.json.JSONObject(new org.json.JSONTokener(fr));
kiteConnect = new KiteConnect(API_KEY);
kiteConnect.setUserId(USER_ID);
kiteConnect.setAccessToken(json.getString("access_token"));
System.out.println("Session loaded successfully");
return true;
} catch (Exception e) {
System.out.println("Failed to load session: " + e.getMessage());
return false;
}
}
private static void loadInstrumentTokens() { /* same as previous */
try {
System.out.println("Downloading NSE instrument list...");
List<Instrument> instruments = kiteConnect.getInstruments("NSE");
for (Instrument i : instruments) {
if ("EQ".equals(i.instrument_type)) {
symbolToToken.put(i.tradingsymbol.toUpperCase(), String.valueOf(i.instrument_token));
}
}
System.out.println("Loaded " + symbolToToken.size() + " equity tokens");
} catch (Exception e) {
System.out.println("Failed to load instruments: " + e.getMessage());
}
}
private static HistoricalData fetchDailyData(String token) throws KiteException, IOException {
Calendar from = Calendar.getInstance();
from.add(Calendar.YEAR, -4);
Calendar to = Calendar.getInstance();
return kiteConnect.getHistoricalData(from.getTime(), to.getTime(), token, "day", false, false);
}
private static void log(String msg) {
String line = LOG_FMT.format(new Date()) + " | " + msg;
System.out.println(line);
if (logWriter != null) {
logWriter.println(line);
logWriter.flush();
}
}
private static void beep(int times) {
for (int i = 0; i < times; i++) {
Toolkit.getDefaultToolkit().beep();
try { Thread.sleep(400); } catch (Exception ignored) {}
}
}
}
Comments
Post a Comment