pytrade-backend / macdstrategies.py
Oviya
Track binaries via Git LFS (analysedata.xlsx, TA_Lib wheel)
66dc1bf
raw
history blame
8.28 kB
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()
}