pytrade-backend / bbstrategies.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
# Bollinger Band Calculation
def calculate_bollinger(data, period=20, stddev=2):
close = data['close']
upper, middle, lower = talib.BBANDS(close, timeperiod=period, nbdevup=stddev, nbdevdn=stddev, matype=0)
return upper, middle, lower
#BB Squeeze breakout/fade after low volatility
def detect_bb_squeeze(close, upper, lower, middle, lookback=20, perc=20):
bandwidth = (upper - lower) / middle
# 20th percentile over the lookback window
thresh = np.percentile(bandwidth.iloc[-lookback:], perc)
if bandwidth.iloc[-1] < thresh:
return "Neutral"
# otherwise fall back to a breakout rule
if close.iloc[-1] > upper.iloc[-1]:
return "Bullish"
elif close.iloc[-1] < lower.iloc[-1]:
return "Bearish"
return "Neutral"
# BB Breakout Detection
def detect_bb_breakout(close, upper, lower):
if close.iloc[-1] > upper.iloc[-1]:
return "Bullish"
elif close.iloc[-1] < lower.iloc[-1]:
return "Bearish"
return "Neutral"
# BB Breakout Reversal
def detect_bb_breakout_reversal(data, upper, lower, middle, lookahead=3):
i = len(data) - lookahead - 1
if i < 0:
return "Neutral"
row = data.iloc[i]
# Bullish Reversal
if row['close'] > upper.iloc[i]:
for j in range(1, lookahead + 1):
next_row = data.iloc[i + j]
if next_row['close'] < upper.iloc[i + j] and next_row['close'] > middle.iloc[i + j]:
return "Bullish"
# Bearish Reversal
elif row['close'] < lower.iloc[i]:
for j in range(1, lookahead + 1):
next_row = data.iloc[i + j]
if next_row['close'] > lower.iloc[i + j] and next_row['close'] < middle.iloc[i + j]:
return "Bearish"
return "Neutral"
# Middle Band Pullback
def detect_middle_band_pullback(close, middle, upper, lower, threshold=0.10, trend_lookback=3):
band_width = upper.iloc[-1] - lower.iloc[-1]
if abs(close.iloc[-1] - middle.iloc[-1]) < band_width * threshold:
trend_above = all(close.iloc[-i] > middle.iloc[-i] for i in range(2, 2 + trend_lookback))
trend_below = all(close.iloc[-i] < middle.iloc[-i] for i in range(2, 2 + trend_lookback))
if trend_above:
return "Bullish"
elif trend_below:
return "Bearish"
return "Neutral"
# Master strategy function
def bollinger_strategies(data):
upper, middle, lower = calculate_bollinger(data)
signals = {
"UpperBand": round(upper.iloc[-1], 2),
"MiddleBand": round(middle.iloc[-1], 2),
"LowerBand": round(lower.iloc[-1], 2),
"BB Squeeze": detect_bb_squeeze(data['close'], upper, lower, middle),
"BB Breakout": detect_bb_breakout(data['close'], upper, lower),
"BB Breakout Reversal": detect_bb_breakout_reversal(data, upper, lower, middle),
"Middle Band Pullback": detect_middle_band_pullback(data['close'], middle, upper, lower)
}
weights = {
"BB Squeeze": 30,
"BB Breakout": 25,
"BB Breakout Reversal": 25,
"Middle Band Pullback": 20
}
total_score = 0
for strategy, weight in weights.items():
signal = signals[strategy]
if "Bullish" in signal or "Breakout Up" in signal or "Squeeze" in signal or "Pullback" in signal:
total_score += weight
elif "Neutral" in signal or "No Breakout" in signal:
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
# API-style function
def get_bollinger_trade_signal(data):
bb_signals, overall_score, final_signal = bollinger_strategies(data)
return {
"bollinger_signals": bb_signals,
"bollinger_score": overall_score,
"bollinger_final_signal": final_signal
}