pytrade-backend / adxstrategies.py
Oviya
Track binaries via Git LFS (analysedata.xlsx, TA_Lib wheel)
66dc1bf
from flask import Flask, request, jsonify
import yfinance as yf
import pandas as pd
import numpy as np
import talib
import datetime
# Calculate ADX, +DI, and -DI values
def calculate_adx(data, period=14):
high_prices = data['high']
low_prices = data['low']
close_prices = data['close']
adx = talib.ADX(high_prices, low_prices, close_prices, timeperiod=period)
plus_di = talib.PLUS_DI(high_prices, low_prices, close_prices, timeperiod=period)
minus_di = talib.MINUS_DI(high_prices, low_prices, close_prices, timeperiod=period)
return adx, plus_di, minus_di
# Detect ADX crossover (directional indicators +DI and -DI)
def adx_di_crossover_strategy(plus_di, minus_di, adx, threshold=20, lookback_days=5):
# We will loop over the last `lookback_days` to check for crossovers
for i in range(-lookback_days, 0):
# Check if ADX is above the threshold
if adx[i] > threshold:
# Bullish condition: +DI crosses above -DI and ADX is above threshold
if plus_di[i] > minus_di[i] and plus_di[i - 1] <= minus_di[i - 1]:
return "Bullish"
# Bearish condition: -DI crosses above +DI and ADX is above threshold
elif minus_di[i] > plus_di[i] and minus_di[i - 1] <= plus_di[i - 1]:
return "Bearish"
return "Neutral"
#ADX Breakout strategy
def adx_breakout_strategy(data, adx, threshold=25):
# Detect breakout condition (ADX above 25, price breaking resistance/support)
if adx[-1] > threshold:
if data['close'][-1] > data['high'][-2]: # Bullish breakout
return "Bullish"
elif data['close'][-1] < data['low'][-2]: # Bearish breakout
return "Bearish"
return "Neutral"
# ADX Slope Strategy
def get_adx_slope_signal(adx, days=5, threshold=0.1):
total_slope = 0
# Calculate slope for each of the last `days`
for i in range(-days, -1):
slope = adx[i + 1] - adx[i]
total_slope += slope
# Average slope
avg_slope = total_slope / (days - 1)
if avg_slope > threshold:
return "Bullish"
elif avg_slope < -threshold:
return "Bearish"
else:
return "Neutral"
# ADX Divergence Strategy
def adx_divergence_strategy(data, adx, threshold=25):
"""
Detects divergence between price and ADX.
A divergence occurs when price makes a new high/low, but ADX does not follow the same direction.
"""
price_high = data['high']
price_low = data['low']
# Checking for divergence
price_divergence_bullish = price_high[-1] > price_high[-2] and adx[-1] < adx[-2]
price_divergence_bearish = price_low[-1] < price_low[-2] and adx[-1] > adx[-2]
if price_divergence_bullish:
return "Bullish"
elif price_divergence_bearish:
return "Bearish"
return "Neutral"
# Main ADX strategy function
def adx_strategies(data):
# Calculate ADX, +DI, and -DI
adx, plus_di, minus_di = calculate_adx(data)
signals = {
"ADX": round(adx.iloc[-1], 2),
"ADX + DI Crossover": adx_di_crossover_strategy(plus_di, minus_di, adx),
"ADX Breakout": adx_breakout_strategy(data, adx),
"ADX Slope": get_adx_slope_signal(adx[-5:]),
"ADX Divergence": adx_divergence_strategy(data, adx)
}
weights = {
"ADX + DI Crossover": 35,
"ADX Breakout": 30,
"ADX Slope": 20,
"ADX Divergence": 15
}
total_score = 0
for strategy, weight in weights.items():
signal = signals[strategy]
if signal == "Bullish":
total_score += weight
elif signal == "Neutral":
total_score += weight * 0.5
overall_percentage = round((total_score / sum(weights.values())) * 100, 2)
if overall_percentage >= 60:
final_signal = "Buy"
elif overall_percentage <= 40:
final_signal = "DBuy"
else:
final_signal = "Neutral"
return signals, overall_percentage, final_signal,adx, plus_di, minus_di
def extract_series(data, series, days=100):
series = pd.Series(series).dropna().tail(days)
series.index = data.index[-len(series):]
series.index = series.index.strftime('%Y-%m-%d')
return series.round(2).to_dict()
# API-style function
def get_adx_trade_signal(data):
adx_signals, overallscore, final_signal,adx, plus_di, minus_di = adx_strategies(data)
return {
"adx_signals": adx_signals,
"adx_score": overallscore,
"adx_final_signal": final_signal,
"ADX_Indicator": extract_series(data, adx),
"PLUS_DI": extract_series(data, plus_di),
"MINUS_DI": extract_series(data, minus_di)
}