pytrade-backend / macdstrategies.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
from collections import OrderedDict
import datetime
# Calculate MACD, Signal and Histogram
def calculate_macdvalue(data, fast=12, slow=26, signal=9):
close_prices = data['close']
# Calculate MACD
macd_line, signal_line, histogram = talib.MACD(
close_prices,
fastperiod=fast,
slowperiod=slow,
signalperiod=signal
)
return macd_line, signal_line, histogram
# MACD Line Crossover - completed
def get_macd_line_crossover_signal(macd, signal):
for i in range(len(macd) - 1):
older_macd = macd[i]
newer_macd = macd[i + 1]
older_signal = signal[i]
newer_signal = signal[i + 1]
# Bullish crossover (MACD crosses above Signal)
if older_macd <= older_signal and newer_macd > newer_signal:
return "Bullish"
# Bearish crossover (MACD crosses below Signal)
elif older_macd >= older_signal and newer_macd < newer_signal:
return "Bearish"
return "Neutral"
# Zero Line Crossover - completed
def get_macd_zero_line_crossover_signal(macd):
for i in range(len(macd) - 1):
older = macd[i]
newer = macd[i + 1]
if older <= 0 and newer > 0:
return "Bullish"
elif older >= 0 and newer < 0:
return "Bearish"
return "Neutral"
# MACD Momentum Signal - completed
def get_macd_momentum_signal(macd, signal, hist):
for i in range(len(macd) - 1):
older_macd = macd[i]
newer_macd = macd[i + 1]
older_signal = signal[i]
newer_signal = signal[i + 1]
current_hist = hist[i + 1] # Use the histogram of the newer point
# Bullish crossover (MACD crosses above Signal) with positive histogram
if older_macd <= older_signal and newer_macd > newer_signal and current_hist > 0:
return "Bullish"
# Bearish crossover (MACD crosses below Signal) with negative histogram
elif older_macd >= older_signal and newer_macd < newer_signal and current_hist < 0:
return "Bearish"
return "Neutral"
# MACD Volume Signal - completed
def get_macd_volume_signal(data, macd, signal):
avg_volume = data['volume'].rolling(window=10).mean()
recent_volume = data['volume'].values[-1:]
recent_avg_volume = avg_volume.values[-1:]
volume_confirm = recent_volume > recent_avg_volume
for i in range(len(macd) - 1):
older_macd = macd[i]
newer_macd = macd[i + 1]
older_signal = signal[i]
newer_signal = signal[i + 1]
if (older_macd <= older_signal and
newer_macd > newer_signal and
volume_confirm):
return "Bullish"
elif (older_macd >= older_signal and
newer_macd < newer_signal and
volume_confirm):
return "Bearish"
return "Neutral"
# MACD Multi-Timeframe - completed
def get_macd_multi_timeframe_confirmation(macd, signal,macd_hr, signal_hr):
for i in range(len(macd) - 1):
older_macd = macd[i]
newer_macd = macd[i + 1]
older_signal = signal[i]
newer_signal = signal[i + 1]
older_macd_hr = macd_hr[i]
newer_macd_hr = macd_hr[i + 1]
older_signal_hr = signal_hr[i]
newer_signal_hr = signal_hr[i + 1]
# Bullish crossover (MACD crosses above Signal)
if older_macd <= older_signal and newer_macd > newer_signal and older_macd_hr <= older_signal_hr and newer_macd_hr > newer_signal_hr:
return "Bullish"
# Bearish crossover (MACD crosses below Signal)
elif older_macd >= older_signal and newer_macd < newer_signal and older_macd_hr >= older_signal_hr and newer_macd_hr < newer_signal_hr:
return "Bearish"
return "Neutral"
# Price and MACD Divergence - completed
def get_macd_divergence_signal(macd, price):
# Bullish Divergence: Price makes lower lows, but MACD makes higher lows
bullish_divergence = None
for i in range(10, len(price)): # Look at the last 5 candles
if price[i] < price[i-1] and macd[i] > macd[i-1]:
bullish_divergence = "Bullish"
break
# Bearish Divergence: Price makes higher highs, but MACD makes lower highs
bearish_divergence = None
for i in range(10, len(price)): # Look at the last 5 candles
if price[i] > price[i-1] and macd[i] < macd[i-1]:
bearish_divergence = "Bearish"
break
if bullish_divergence:
return bullish_divergence
elif bearish_divergence:
return bearish_divergence
else:
return "Neutral"
# MACD Hidden Divergence - completed
def get_macd_hidden_divergence_signal(macd, price):
# Bullish Hidden Divergence: Price makes a higher low, but MACD makes a lower low
bullish_hidden_divergence = None
for i in range(10, len(price)): # Look at the last 5 candles
if price[i] > price[i-10] and macd[i] < macd[i-10]:
bullish_hidden_divergence = "Bullish"
break
# Bearish Hidden Divergence: Price makes a lower high, but MACD makes a higher high
bearish_hidden_divergence = None
for i in range(10, len(price)): # Look at the last 5 candles
if price[i] < price[i-10] and macd[i] > macd[i-10]:
bearish_hidden_divergence = "Bearish"
break
if bullish_hidden_divergence:
return bullish_hidden_divergence
elif bearish_hidden_divergence:
return bearish_hidden_divergence
else:
return "Neutral"
# macd_strategies and get_macd_trade_signal functions
def macd_strategies(data):
macd, signal, hist = calculate_macdvalue(data)
latest_macd = macd[-1]
signals = {
"MACD": round(latest_macd,2),
"MACD Line Crossover": get_macd_line_crossover_signal(macd[-5:],signal[-5:]),
"MACD Zero-Line Crossover": get_macd_zero_line_crossover_signal(macd[-5:]),
"MACD Divergence": get_macd_divergence_signal(macd[-10:], data['close'][-10:]),
"Hidden Divergence": get_macd_hidden_divergence_signal(macd[-10:], data['close'][-10:]),
"MACD Volume": get_macd_volume_signal(data, macd[-5:],signal[-5:]),
"MACD Momentum": get_macd_momentum_signal(macd[-5:],signal[-5:],hist[-5:]),
}
macd_signal_weights = {
"MACD Line Crossover": 25,
"MACD Zero-Line Crossover": 15,
"MACD Divergence": 20,
"Hidden Divergence": 10,
"MACD Volume": 15,
"MACD Momentum": 15,
}
total_score = 0
for strategy, weight in macd_signal_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(macd_signal_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
def get_macd_trade_signal(data):
macd_signals, overallscore, final_signal = macd_strategies(data)
macd_line, signal_line, hist = calculate_macdvalue(data)
# Format and convert MACD and Signal Line for last 100 days
macd_series = pd.Series(macd_line, index=data.index).dropna().tail(100)
signal_series = pd.Series(signal_line, index=data.index).dropna().tail(100)
macd_series.index = macd_series.index.strftime('%Y-%m-%d')
signal_series.index = signal_series.index.strftime('%Y-%m-%d')
hist_series = pd.Series(hist, index=data.index).dropna().tail(100)
hist_series.index = hist_series.index.strftime('%Y-%m-%d')
return {
"macd_signals": macd_signals,
"macd_score": overallscore,
"macd_final_signal": final_signal,
"macd_line": macd_series.round(2).to_dict(),
"macd_signal_line": signal_series.round(2).to_dict(),
"macd_histogram": hist_series.round(2).to_dict()
}