#!/usr/bin/python

# uses 3 Bollinger bands with range 20 and rate 2, 2.5 and 3
# the signal is generated when the lower or upper band is crossed

import yfinance as yf
import time
from datetime import datetime
import sys

# getData - get the data (5, 15, 30 minutes) using the ticker
def getData(arg):
 ticker = yf.Ticker(arg)
 d5m = ticker.history(period = "1d", interval = "5m")["Close"]
 d15m = ticker.history(period = "1d", interval = "15m")["Close"]
 d30m = ticker.history(period = "1d", interval = "30m")["Close"]
 return d5m, d15m, d30m

# get the SMA, needed for Bollinger
def get_sma(prices, rate):
 return prices.rolling(rate).mean()

# get the Bollinger bands
def get_bollinger_bands(prices, rate, coef=2):
 sma = get_sma(prices, rate)
 std = prices.rolling(rate).std()
 bollinger_up = sma + std * coef
 bollinger_down = sma - std * coef
 return bollinger_up, bollinger_down

# the main procedure, to be called every minute
def get_and_process():
 # print the local time
 print(datetime.now().strftime("%H:%M:%S"))
 # read the assets file
 assetsfile = open("assets.txt", "r")
 assets = assetsfile.read().splitlines()
 assetsfile.close()
 # for each asset
 for asset in assets:
  # (try to) get the data: this day, timeframes 5m, 15m, 30m
  try:
   data5m, data15m, data30m = getData(asset)

   # get the Bollinger bands from each dataframe for 5, 10 and 30 iterations
   # and calculate the signals for each one
   sig5up = 0
   sig5down = 0
   sig15up = 0
   sig15down = 0
   sig30up = 0
   sig30down = 0

   # use the rate 20 and coef 2, 2.5, 3
   # 5-min, coef 2
   bollinger_up, bollinger_down = get_bollinger_bands(data5m, 20, 2)
   if (data5m.values[-1] < bollinger_down.values[-1]): sig5up += 1
   if (data5m.values[-1] > bollinger_up.values[-1]): sig5down += 1
   # 5-min, coef 2.5
   bollinger_up, bollinger_down = get_bollinger_bands(data5m, 20, 2.5)
   if (data5m.values[-1] < bollinger_down.values[-1]): sig5up += 1
   if (data5m.values[-1] > bollinger_up.values[-1]): sig5down += 1
   # 5-min, coef 3
   bollinger_up, bollinger_down = get_bollinger_bands(data5m, 20, 3)
   if (data5m.values[-1] < bollinger_down.values[-1]): sig5up += 1
   if (data5m.values[-1] > bollinger_up.values[-1]): sig5down += 1
   # 15-min, coef 2
   bollinger_up, bollinger_down = get_bollinger_bands(data15m, 20, 2)
   if (data15m.values[-1] < bollinger_down.values[-1]): sig15up += 1
   if (data15m.values[-1] > bollinger_up.values[-1]): sig15down += 1
   # 15-min, coef 2.5
   bollinger_up, bollinger_down = get_bollinger_bands(data15m, 20, 2.5)
   if (data15m.values[-1] < bollinger_down.values[-1]): sig15up += 1
   if (data15m.values[-1] > bollinger_up.values[-1]): sig15down += 1
   # 15-min, coef 3
   bollinger_up, bollinger_down = get_bollinger_bands(data15m, 20, 3)
   if (data15m.values[-1] < bollinger_down.values[-1]): sig15up += 1
   if (data15m.values[-1] > bollinger_up.values[-1]): sig15down += 1
   # 30-min, coef 2
   bollinger_up, bollinger_down = get_bollinger_bands(data30m, 20, 2)
   if (data30m.values[-1] < bollinger_down.values[-1]): sig30up += 1
   if (data30m.values[-1] > bollinger_up.values[-1]): sig30down += 1
   # 30-min, coef 2.5
   bollinger_up, bollinger_down = get_bollinger_bands(data30m, 20, 2.5)
   if (data30m.values[-1] < bollinger_down.values[-1]): sig30up += 1
   if (data30m.values[-1] > bollinger_up.values[-1]): sig30down += 1
   # 30-min, coef 3
   bollinger_up, bollinger_down = get_bollinger_bands(data30m, 20, 3)
   if (data30m.values[-1] < bollinger_down.values[-1]): sig30up += 1
   if (data30m.values[-1] > bollinger_up.values[-1]): sig30down += 1

  # if no luck with getting the information
  # (no data or no connection)
  # set the signals to 0
  except:
   sig5up = 0
   sig5down = 0
   sig15up = 0
   sig15down = 0
   sig30up = 0
   sig30down = 0
  # show the information for the current asset (if any signal)
  if (sig5up > 0):
   print(asset + " may go UP at 5-min (" + str(sig5up) + "/3)")
  if (sig5down > 0):
   print(asset + " may go DOWN at 5-min (" + str(sig5down) + "/3)")
  if (sig15up > 0):
   print(asset + " may go UP at 15-min (" + str(sig15up) + "/3)")
  if (sig15down > 0):
   print(asset + " may go DOWN at 15-min (" + str(sig15down) + "/3)")
  if (sig30up > 0):
   print(asset + " may go UP at 30-min (" + str(sig30up) + "/3)")
  if (sig30down > 0):
   print(asset + " may go DOWN at 30-min (" + str(sig30down) + "/3)")

while True:
 get_and_process()
 time.sleep(60)
