Categories
Python

Coding Richard Dawkins’ ‘Me Thinks It is a Like a Weasel’ in Python

https://www.youtube.com/watch?v=WekRrOXZWvk
#!/usr/bin/env python3
import random
import string

TARGET = ''
TARGET_LEN = 0
LETTERS = string.ascii_uppercase + ' ' + string.punctuation
GENERATIONS = 100
GENERATION_POPULATION = 100

allGenerations = []

bestString = {
    'string': '',
    'base_for_new_generation': '',
    'score': 0
}

def randomString(stringLength):
    return ''.join(random.choice(LETTERS) for i in range(stringLength));

def replaceNoneMatchesWithRandomChar():
    tempString = bestString['base_for_new_generation']
    for i, letter in enumerate(tempString):
        if letter == '*':
            tempString = switchChar(tempString, i, random.choice(LETTERS))
    return tempString

def switchChar(string, index, rand_char):
    return string[:index]+rand_char+string[index+1:]

def createNewGeneration():
    constructNewBaseForGeneration(bestString['string'])
    allGenerations.append([replaceNoneMatchesWithRandomChar() for _ in range(GENERATION_POPULATION)])

def constructNewBaseForGeneration(bestMatch):
    base_for_new_generation = ''
    for i in range(TARGET_LEN):
        if TARGET[i] == bestMatch[i]:
            base_for_new_generation = base_for_new_generation + bestString['string'][i]
        else:
            # No match so replace with '*' to make replacing with random char easier
            # This enables us to create x number of strings based on the same parent
            base_for_new_generation = base_for_new_generation + '*'
    bestString['base_for_new_generation'] = base_for_new_generation

def scoreString(string):
    score = 0
    for i in range(TARGET_LEN):
        if TARGET[i] == string[i]:
            score = score + 1
    return score

def updateBestString(string, score):
    bestString['string'] = string
    bestString['score'] = score


def checkMatch():
    latest_generation = allGenerations[-1]
    for string in latest_generation:
        score = scoreString(string)
        if score > bestString['score']:
            updateBestString(string, score)

def createInitialStrings():
    allGenerations.append([randomString(TARGET_LEN) for _ in range(GENERATION_POPULATION)])

def printBestString():
    print('Generation ' + str(len(allGenerations)))
    print('Current best string ' + bestString['string'])


def monkeys(target):
    global TARGET 
    TARGET = target
    global TARGET_LEN 
    TARGET_LEN = len(TARGET)
    createInitialStrings()
    checkMatch()
    printBestString()
    for i in range(GENERATIONS):
        if bestString['string'] == TARGET:
            printBestString()
            print('Script Complete Matched in ' + str(len(allGenerations)) + ' generations')
            return len(allGenerations)
        createNewGeneration()
        checkMatch()
        printBestString()


if __name__ == '__main__':
    monkeys(input('Enter a string for the monkeys to type: ').upper())
Categories
Python

KeepGrabbing.py Explained Aaron Swartz JSTOR Scrapping

https://www.youtube.com/watch?v=0sJ7CVos5bQ&feature=youtu.be

Here is my annotated version of keepgrabbing.py

'''
This is written in python2.

I because we don't have the URL which is reacted, some of the notes here
are my best interpretation.

The imports:
subprocess - allows you to create new processes from the python script.
   subprocesses are child processes created from another process.
urllib - allows you to retrieve resources from URL.
random - generates pseudo-random numbers (i.e. not truly random numbers)
sys - imported later. Enables access to parameters and functions specific
   to the machine that is running the code.
'''

import subprocess, urllib, random
'''
    This is a custom exception class, that when raised, causes the whole script to exit.
'''
class NoBlocks(Exception): pass
'''
    This function reads from a URL which has been reacted by the courts.
    It looks like this function called to custom url which was likely
    set up by Swartz himself, which had a list of URLs linking to PDFs to
    download.

    It is likely the case that Swartz had this grab page setup and would
    control and modify it from out side of the MIT campus in order to
    direct the script to download the PDFs he wanted.

    The first line in this function calls urllib.urlopen().read and saves the
    response of this call to a variable called 'r'. The urlopen function
    reads from a URL and returns a file-like object from the contents of the
    external resource that the URL points to. The read function that is called
    on this simply reads the byte contents and returns them.

    The second line of this function checks to see if there is HTML in the
    retrieved page. If there is then it raises a NoBlocks exception and
    exits the script. It is likely that the URL that is reacted simply
    was a text file with the PDFs Swartz wanted to download. When he
    wanted to stop the script he could simply swap this text file for a HTML
    file and the script would exit.

    The split function simply takes a string and splits it into a list and by
    default, it will split the string at every space, which is what Aaron is
    doing here.
'''
def getblocks():
    r = urllib.urlopen("http://{?REDACTED?}/grab").read()
    if '<html' in r.lower(): raise NoBlocks
    return r.split()

'''
    The next 5 lines of code are concerned with taking the arguments to the
    script from the sys.argv and if there is one present adding it to a
    variable as a list with the string --socks5 as the first string in the list.

    Note that it takes the second element in the sys.argv list as the first
    element in the sys.argv list is the name of the script.

    This prefix variable will be used in a lamda expression below.

    Basically, this prefix is used to make the script connect to JSTOR via a
    proxy or just though the computer's internet connection (which Aaron left
    a command about, suggesting this was an ethernet connection, which makes
    sense as the computer that Aaron used to run this script was in a store
    cupboard connected to the MIT network)

    This line may mean that Aaron could run this script from outside the
    MIT network, but that is just speculation.
'''
import sys
if len(sys.argv) > 1:
    prefix = ['--socks5', sys.argv[1]]
else:
    prefix = []#'-interface','eth0:1']
'''
    The next line declares a lambda function which is saved to the variable
    called line.

    This lambda expression takes a single argument, which is the name of the
    PDF that the script is going to download.

    This lambda expression will later be used as part of a subprocess call
    later in the script.

    It defines a curl request. The curl command is a command which allows you
    to transfer data to or from a URL, i.e upload or download from a url.
    The curl request is with a proxy to connect via (depending on the
    conditional above as mentioned). Next, it defines a cookie, which is simply
    the string TENACIOUS= followed by a random 3-digit number. This cookie,
    will make the server responding to this curl request think that it is coming
    from a real user as opposed to a script. The next thing this function does
    is define the output of this curl request: the pdf file name to a directory
    called pdfs. The rest of this lambda creates the url of the PDF from which
    to download the PDF with using curl.

'''
line = lambda x: ['curl'] + prefix + ['-H', "Cookie: TENACIOUS=" + str(random.random())[3:], '-o', 'pdfs/' + str(x) + '.pdf', "http://www.jstor.org/stable/pdfplus/" + str(x) + ".pdf?acceptTC=true"]

'''
    This next section of code. Defines an infinite loop, which is the part of
    the code that composes everything else.

    First it calls the getblocks from earlier and saves the resulting list of
    PDFs to a variable called blocks.

    It then iterates over these, printing them to the console and then calling
    the line lambda from earlier in a subprocess.Popen call. Subprocess Popen
    will create a new process, in this case the curl request that will
    download the current PDF. Then the script will block until this subprocess
    finishes, i.e. it will wait until the PDF is finished downloading and then
    it will move on to the next PDF.
'''
while 1:
    blocks = getblocks()
    for block in blocks:
        print block
        subprocess.Popen(line(block)).wait()

Here is the original version of keepgrabbing.py

import subprocess, urllib, random
class NoBlocks(Exception): pass
def getblocks():
    r = urllib.urlopen("http://{?REDACTED?}/grab").read()
    if '<html' in r.lower(): raise NoBlocks
    return r.split()


import sys
if len(sys.argv) > 1:
    prefix = ['--socks5', sys.argv[1]]
else:
    prefix = []#'-interface','eth0:1']
line = lambda x: ['curl'] + prefix + ['-H', "Cookie: TENACIOUS=" + str(random.random())[3:], '-o', 'pdfs/' + str(x) + '.pdf', "http://www.jstor.org/stable/pdfplus/" + str(x) + ".pdf?acceptTC=true"]


while 1:
    blocks = getblocks()
    for block in blocks:
        print block
        subprocess.Popen(line(block)).wait()
Categories
Python Python for Finance

How to Correlate Stocks with Python and Seaborn | Python for Finance

https://youtu.be/Zb3Xda7MvE8

In this video, we are going to correlate stocks with Python. Once we have correlated the stocks, we will then plot the correlation using the Seaborn library.

Get the tickers here:


Get the code here:

#!/usr/bin/env python3
import csv
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn
from pandas_datareader import data
from datetime import datetime

def get_stocks():
    tickers = []
    with open('tickers.csv') as ticker_file:
        for ticker in ticker_file:
            tickers.append(ticker.strip())
    return tickers

start_date = '2005-01-01'
end_date = datetime.now()

def add_column(stock_data, name, value):
    stock_data[name] = value
    return stock_data

def get_data(tickers):
    stocks = []
    for ticker in tickers: 
        try: 
            stock_data = data.DataReader(ticker, 'yahoo', start=start_date, end=end_date)
            stocks.append(add_column(stock_data, 'ticker', ticker))
        except:
            print('Error ticker: ' + ticker)
    return pd.concat(stocks)

def correlate(df):
    df = df.reset_index()
    df = df[['Date', 'Adj Close', 'ticker']]
    pivot = df.pivot('Date', 'ticker', 'Adj Close').reset_index()

    return pivot.corr(method='pearson')

def plot(data):
    mask = np.zeros_like(data)
    mask[np.triu_indices_from(mask)] = True
    seaborn.heatmap(data, cmap='Blues', vmax=1.0, vmin=-1.0, mask = mask)
    plt.title('The correlation between stocks')
    plt.show()


if __name__ == '__main__':
    data = correlate(get_data(get_stocks()[:10]))
    plot(data)
Categories
Python Python for Finance

Finding Weekly Stock Return with Python and Pandas

Get the tickers file from this video, please note this is different from the other ones in previous videos:



Code:

#!/usr/bin/env python
from pandas_datareader import data
from pandas_datareader._utils import RemoteDataError
import pandas as pd
import numpy as np
from operator import itemgetter
import datetime
import csv

weekly_returns = []

def get_stocks():
    tickers = []
    with open('tickers.csv') as ticker_file:
        for ticker in ticker_file:
            tickers.append(ticker.strip())
    return tickers

def to_csv(stocks):
    with open('weekly_returns.csv', 'w') as output:
        writer = csv.writer(output)
        writer.writerow(stocks[0].keys())
        for stock in stocks:
            writer.writerow(stock.values())

def reindex_column(panel_data, key, all_weekdays):
    column = panel_data[key].reindex(all_weekdays)
    return column.fillna(method='ffill')

def calc_return(current, previous):
    return (current - previous) / current * 100

def get_last_week_return(ticker):
    start_date = '2005-01-01'
    end_date = '2020-07-03'

    all_weekdays = pd.date_range(start=start_date, end=end_date, freq='B')

    try: 
        panel_data = data.DataReader(ticker, 'yahoo', start_date, end_date)
        adj_close = reindex_column(panel_data, 'Adj Close', all_weekdays)

        current_price = adj_close[-1]
        last_week_close = adj_close[-6]

        weekly_return = calc_return(current_price, last_week_close)

        weekly_returns.append({
            'ticker': ticker, 
            'week_ending': end_date,
            'current_price': current_price,
            'last_week_close': last_week_close,
            'weekly_return': weekly_return
        })

    except: 
        print('Error for ' + ticker)

if __name__ == '__main__': 
    for ticker in get_stocks()[:5]:
        get_last_week_return(ticker)
    to_csv(weekly_returns)
Categories
Python Python for Finance

Creating Stock Market Summary Emails with Python

https://youtu.be/gIMOm0DFI5A

Get the tickers file:



Get the code:

weekly_returns.py

#!/usr/bin/python3
from stock_data import get_week_summary
from emailer import send_weekly_summary

import csv

def get_stocks():
    tickers = []
    with open('tickers.csv') as ticker_file:
        for ticker in ticker_file:
            tickers.append(ticker.strip())
    return tickers

if __name__ == '__main__':
    summary = get_week_summary(get_stocks()[:5], 5)
    send_weekly_summary(summary)

stock_data.py

#!/usr/bin/python3
from pandas_datareader import data
import pandas as pd
import numpy as np
from operator import itemgetter
import datetime

weekly_returns = []

def reindex_column(panel_data, key, all_weekdays):
    column = panel_data[key].reindex(all_weekdays)
    return column.fillna(method='ffill')

def calc_return(current, previous):
    return (current / previous) * 100

def sort_by_weekly_returns(stocks, risers):
    return sorted(stocks, key=itemgetter('weekly_return'), reverse=risers) 

def find_biggest_fallers(stocks, number):
    return sort_by_weekly_returns(stocks, False)[:number]

def find_biggest_risers(stocks, number):
    return sort_by_weekly_returns(stocks, True)[:number]

def get_last_week(ticker): 
    start_date = '2005-01-01'
    end_date = '2020-07-03'

    all_weekdays = pd.date_range(start=start_date, end=end_date, freq='B')

    panel_data = data.DataReader(ticker, 'yahoo', start_date, end_date)
    adj_close = reindex_column(panel_data, 'Adj Close', all_weekdays)

    current_price = adj_close[-1]
    last_week_close = adj_close[-6]

    return { 
            'ticker': ticker, 
            'week_ending': end_date, 
            'current_price': current_price, 
            'previous_price': last_week_close,
            'weekly_return': calc_return(current_price, last_week_close)
            }

def get_week_summary(tickers, number): 
    for ticker in tickers: 
        weekly_returns.append(get_last_week(ticker))

    return {
            'biggest_risers': find_biggest_risers(weekly_returns, number),
            'biggest_fallers': find_biggest_fallers(weekly_returns, number)
            }

emailer.py

#!/usr/bin/python3
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

from email_tables import get_biggest_risers_and_fallers
from email_server import get_server
from email_server import get_email

def send_weekly_summary(data):
    msg = MIMEMultipart('alternative')
    msg['To'] = EMAIL HERE 
    msg['From'] = get_email()
    msg['Subject'] = 'Biggest Risers and Fallers This Week'

    text = MIMEText('Please enable HTML, you fool', 'plain')
    html = MIMEText(get_biggest_risers_and_fallers(data), 'html')

    msg.attach(text)
    msg.attach(html)

    server = get_server()

    server.sendmail(msg['From'], msg['To'], str(msg))
    server.quit()

email_tables.py

#!/usr/bin/python3
import dominate
from dominate.tags import *
from decimal import Decimal

def round_decimal(x):
    decimal_value = Decimal(x)
    return decimal_value.quantize(Decimal(10) ** -2)

def get_change_single(last_change):
    return str(round_decimal((last_change - 100.00)))

def get_weekly_table(data, direction):
    table_headers = data[0].keys()

    doc = dominate.document(title='Biggest Stock ' + direction + ' This Week')

    with doc: 
        with table(id='stock_table'):
            caption(h3('Biggest {} This Week'.format(direction)))
            with thead():
                for header in table_headers:
                    th(header)
            with tbody():
                for stock in data:
                    with tr():
                        for header in table_headers:
                            if 'weekly_return' in header: 
                                td(get_change_single(stock[header]) + '%')
                                continue
                            if 'price' in header: 
                                td(round_decimal(stock[header]))
                                continue
                            td(stock[header])

    return str(doc)


def get_biggest_risers_and_fallers(data):
    return get_weekly_table(data['biggest_risers'], 'Risers') + '</br></br>' + get_weekly_table(data['biggest_fallers'], 'Fallers') 

email_server.sample.py

#!/usr/bin/python3
import smtplib

EMAIL  =
PWD    = 
SMTP_SERVER = 
SMTP_PORT   = 

def get_server():
    server = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
    server.starttls()
    server.login(EMAIL, PWD)
    return server

def get_email():
    return EMAIL
Categories
Python

Blocking Spotify Adverts with Python and Selenium

https://youtu.be/xZxaylG2wWQ
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.action_chains import ActionChains
import time

from utils import *

driver = webdriver.Chrome()
driver.get('http://open.spotify.com')
driver.maximize_window()

wait = WebDriverWait(driver, 10)

mute_status = False

def login():
    login_btn = driver.find_element_by_xpath("//button[text()='Log in']")
    login_btn.click()
    wait.until(EC.visibility_of_element_located((By.ID, 'login-username')))
    type_text(getUsername())
    tab()
    type_text(getPassword())
    times(tab, 2)
    enter()

def times(fn, times):
    for _ in range(0, times):
        fn()
    
def type_text(text):
    actions = ActionChains(driver)
    actions.send_keys(text) 
    actions.perform()

def press_key(key):
    type_text(key)

def tab():
    press_key(Keys.TAB)

def enter():
    press_key(Keys.ENTER)

def mute():
    mute_btn = driver.find_element_by_xpath("//button[contains(@class, 'volume-bar__icon')]")
    mute_btn.click()

def unmute():
    mute()

def now_playing_ad():
    now_playing_el = driver.find_elements_by_class_name('now-playing')
    return 'advert' in ''.join(el.text for el in now_playing_el).lower()

login()

while True:
    if now_playing_ad() == True and mute_status == False: 
        mute()
        mute_status = True
    elif now_playing_ad() == False and mute_status == True:
        unmute()
        mute_status = False
    else:
        pass


Categories
Python Python for Finance

Find Dividend Paying Stocks with Python

In this tutorial, we cover finding dividend-paying stocks with python.

The reason I created this tutorial and this script is because I wanted to quickly get data about stock dividends, and I could not find any good free APIs to use. So the solution I settled on was to use web scraping.

Luckily, there is a great python module for web scraping called Beautiful Soup.

The website we are going to scrape is:

https://www.lse.co.uk/share-fundamentals.asp?shareprice=

At the end of this url we can place the stock ticker for example

https://www.lse.co.uk/share-fundamentals.asp?shareprice=UU.

Looking at the website, we can see the dividend rate and the dividend yield in the second market data table:

See the dividend and the yield of United Utilities at the bottom of the second table.

So we want to get this data, but for any stock that is listed on the LSE website.

All we need to do to change the company is swap the ticker at the end of the URL. Now, you may have your own list of tickers that you are interested in, but if you don’t there is a download form at the bottom of this webpage, where you can download a CSV file containing a list of stock tickers from the FTSE 250 index.

As it is less about this tutorial, but I don’t want to miss any minor bits of information, we are going to quickly create the starting point for our script, which I will briefly explain in inline comments:

# These are our imports, external modules which 
# will help us. 
from bs4 import BeautifulSoup as bs # Used for scraping data
import csv # Used to get and write to CSV
import requests # Used to access the external URL (the webpage)

'''
 All this function is doing is reading from our 
 tickers.csv file (which should be saved in the 
 same location as your python script) and returning
 them in a list.
'''
def get_tickers():
    tickers = []
    with open('tickers.csv') as ticker_file:
        for ticker in ticker_file:
            tickers.append(ticker.strip())
    return tickers

 '''
 This method takes a list of dictionaries 
 and uses it to write a CSV file called 
 dividends.csv. We will use this last.
 '''
def to_csv(stocks):
    with open('dividends.csv', 'w') as output:
        writer = csv.writer(output)
        writer.writerow(stocks[0].keys())
        for stock in stocks:
            writer.writerow(stock.values())

'''
This method gets the webpage we want and returns
the html as a beautifulsoup object which we 
can easily scrape for data. 
'''
def get_soup(url):
    return bs(requests.get(url).text, 'html.parser')
'''
This is our entry point.
'''
if __name__ == '__main__':
    dividends = [] # Create an empty list
    for ticker in get_tickers(): # Iterate over the tickers
      # Add the dividend data to the dividends list
        dividends.append(get_data(ticker))
    # Write the dividends data to CSV.
    to_csv(dividends)

Now we need to find the HTML and information about the dividend and yield cells in the table.

To do that, right click on one of the cells and click ‘inspect element’

Here we can see that the table has a class of ‘sp-fundamentals-info__table’, and the table row contains a <th> element and a <td> element which has the dividend rate in.

It’s important to note that there are three tables with class ‘sp-fundamentals-info__table’ on this page. We want to get the second one, which in code will be [1], because lists start at 0.

Note also that the dividend rate is the 6th row in the table, and the dividend yield is the 7th. So that when we get this data from a list, we will be getting the elements 5 and 6.

So now we have all the information we need. Let’s start coding the get_data method.

First let’s get the soup object made of the webpage for the stock that we are interested in:

def get_data(ticker):
    url = 'https://www.lse.co.uk/share-fundamentals.asp?shareprice='
    soup = get_soup(url + ticker)

Next we should open a try-except block.

Why?

Well there a number of things that could go wrong here, and it would be boring and error-prone to write code for all of the possible cases that could go wrong. So instead, we’ll just do a blanket exception. That way, if there is no dividend, or that webpage doesn’t have the information we want or the request fails, we can still carry on with the script.

Note that this approach is lazy, and shouldn’t be used in production as you would want to write cases for everything that could go wrong and handle them in different ways. But for the purposes of this tutorial, it’s totally unnecessary.

The first thing we are going to do in our try block is find the table that we are interested in. To do this we are going to use the Beautiful Soup method find_all to find all of the table elements with the class: ‘sp-fundamentals-info__table’ and then we’re going to select the second one with [1].

 try: 
        table = soup.find_all('table', attrs={'class', 'sp-fundamentals-info__table'})[1]

Next we need to get the dividend and the dividend yield information. To do this we will find all of the <tr> elements in the table, select the 5, and 6 elements respectively and then use the BeautifulSoup find method to find the <td> element which contains the information we are interested in. Finally, we call the .text method, which, as you would expect returns the text contained within the element.

dividend = table.find_all('tr')[5].find('td').text
div_yield = table.find_all('tr')[6].find('td').text

Next we can print the information to the console, so we can see what’s happening as the script is running, and then we can return a dictionary object with the stock ticker, the dividend, and the dividend yield. This will form the columns of our dividend CSV file later.

print(f'Dividend for {ticker} : {dividend}')

        return {
                'ticker': ticker, 
                'dividend': dividend, 
                'yield': div_yield
               }

Finally, we need to add the except block to the try block. Inside of which we are just simply going to log to the console that we can’t find dividend information for that particular stock.

except: 
        print('No information available for ', ticker)

And that’s it. You can now run the code and it will output a file called dividends.csv. This file will contain a table of stocks which pay dividends along with their yields.

See the stock to CSV video mentioned within this tutorial:

https://studio.youtube.com/video/LzkpESUIoYk/edit

Get the tickers file from this video:


Get the code from this video:

from bs4 import BeautifulSoup as bs
import csv 
import requests 

def get_tickers():
    tickers = []
    with open('tickers.csv') as ticker_file:
        for ticker in ticker_file:
            tickers.append(ticker.strip())
    return tickers

def to_csv(stocks):
    with open('dividends.csv', 'w') as output:
        writer = csv.writer(output)
        writer.writerow(stocks[0].keys())
        for stock in stocks:
            writer.writerow(stock.values())

def get_soup(url):
    return bs(requests.get(url).text, 'html.parser')

def get_data(ticker):
    url = 'https://www.lse.co.uk/share-fundamentals.asp?shareprice='
    soup = get_soup(url + ticker)
    try: 
        table = soup.find_all('table', attrs={'class', 'sp-fundamentals-info__table'})[1]
        dividend = table.find_all('tr')[5].find('td').text
        div_yield = table.find_all('tr')[6].find('td').text

        print(f'Dividend for {ticker} : {dividend}')

        return {
                'ticker': ticker, 
                'dividend': dividend, 
                'yield': div_yield
               }
    except: 
        print('No information available for ', ticker)


if __name__ == '__main__':
    dividends = []
    for ticker in get_tickers():
        dividends.append(get_data(ticker))
    to_csv(dividends)
Categories
Python Web Scraping for Beginners

Webscraping Stock Data with Selenium and Python

https://youtu.be/8aedS8sQ9lg

run pip install selenium

Install the chromedriver – –https://chromedriver.chromium.org/

In case you’re not on a mac https://zwbetz.com/download-chromedriver-binary-and-add-to-your-path-for-automated-functional-testing/

Make sure that you choose the version that matches the version of Chrome that you currently have installed. This will most likely be the stable release.

Then run the following:

cd Downloads Or to whatever directory you saved the unzipped chromedriver to.

mkdir ~/bin

mv chromedriver ~/bin

cd ~/bin

chmod +x chromedriver

vi ~/.zshrc (or vi ~/.bash_profile if you don’t have zsh installed)

Add this line: export PATH=”​HOME/bin”

source ~/.zshrc or source ~/.bash_profile

If you’re on Mac OS catalina, you will need to allow the chrome driver to execute by going to the security sections of your system preferences.

Get the xPath finder chrome extension here: https://chrome.google.com/webstore/detail/xpath-finder/ihnknokegkbpmofmafnkoadfjkhlogph/related?hl=en

Here is the code for this video:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
import time

driver = webdriver.Chrome()
driver.get('https://www.londonstockexchange.com/prices-and-markets/stocks/stocks-and-prices.htm')

wait = WebDriverWait(driver, 10)

def search(ticker):
    searchEl = driver.find_element_by_id('head_solr_search_input')
    searchEl.send_keys(ticker)
    wait.until(EC.visibility_of_element_located((By.CLASS_NAME, 'ui-menu-item')))
    searchEl.send_keys(Keys.DOWN)
    searchEl.send_keys(Keys.DOWN)
    searchEl.send_keys(Keys.ENTER)


def get_stock_url(): 
    return driver.current_url

def get_last_price():  
    return driver.find_element_by_xpath("/html/body/div[4]/div/div[3]/div[2]/div[1]/div[5]/div[1]/table/tbody/tr[1]/td[2]").text 

search('UU') 
print(get_stock_url())
print(get_last_price())
time.sleep(3)

driver.quit()
Categories
Python

Control Mouse and Keyboard with Python

https://youtu.be/Zlijb2_oDto

In this video we cover how you can automate controlling the keyboard and the mouse with Python and a module called pyautogui.

Here is the code from this video:

import pyautogui as gui
import time 

ANS_PREFIX = '    *'
Q_PREFIX = '* '

def tab():
    gui.press('tab')

def enter():
    gui.keyDown('command')
    gui.press('enter')
    gui.keyUp('command')

def add_question_answer(anki):
    time.sleep(0.1)
    gui.typewrite(anki['question'])
    tab()
    gui.typewrite(anki['answer'])
    enter()
    time.sleep(0.1)

def create_anki_struct(question, answer):
    return {
            'question': question.strip(Q_PREFIX),
            'answer': answer.strip(ANS_PREFIX)
        }

with open('points_anki.txt', 'r') as ankis: 
    time.sleep(1)
    ankis = ankis.readlines()
    for i in range(0, len(ankis), 2):
        add_question_answer(create_anki_struct(ankis[i], ankis[i+1]))
Categories
Python Python for Finance

Calculating Year-to-Date Stock Returns with Python

Download the start files required to follow along with the video:


Get the code from this video:

from pandas_datareader import data
import pandas as pd
import numpy as np
import datetime

from tickers import get_tickers
from tickers import check_dot

def reindex_column(panel_data, key, dates):
    column = panel_data[key].reindex(dates)
    return column.dropna()

def get_ytd(ticker):
    ticker_l = check_dot(ticker)
    now = datetime.datetime.now()
    start_date = now.strftime('%Y') + '-01-01'
    end_date = str(now.strftime('%Y-%m-%d'))
    all_business_days = pd.date_range(start=start_date, end=end_date, freq='B')
    try: 
        panel_data = data.DataReader(ticker_l, 'yahoo', start_date, end_date)
        adj_close = reindex_column(panel_data, 'Adj Close', all_business_days)
        current_price = np.mean(adj_close.tail(1))
        start_year_price = np.mean(adj_close[0])
        ytd = (current_price / start_year_price) * 100

        stock = {
                'ticker': ticker, 
                'date': end_date, 
                'current_price': current_price,
                'ytd': ytd
                }

        print(stock)

    except:
        print('Error for ' + ticker_l)


if __name__ == '__main__': 
    for ticker in get_tickers():
        get_ytd(ticker)