Tag Stocks

Posts: 68

The Bear Market is Roaring

No matter what the Fed does it can't stop this Bear Market. Everyone's afraid of Covid-19 but I'm willing to bet there's a major structural event happening under the price currents. I'm not one to catch a falling knife so I'm staying on the sidelines for a while longer. Why? Sadly, I think the positive cases of Covid-19 will increase and so will the fatalities. We haven't seen complete panic yet but when a few 'rich' people or politicians get sick and even die then it will hit everyone across all economic classes.

S&P5000, 03/23/2020

Price moves have been so violent and sudden that this is mindboggling. We're now eating away at gains made during the Obama years. I think we might test 1880-ish on the S&P500. That goes back to early February 2016.

comments

Stock and Fund Shopping List

The markets have been in a complete freefall over the past few weeks. The likely culprit is Trump's mishandling of the Covid-19 (aka Coronavirus) response and overinflated prices. Who knows what is the real market contagion here but I think it's time to make a shopping list.

MSFT, 03/19/2020

AAPL, 03/19/2020

With free falls in some of my favorite holdings (MSFT and AAPL), I can't but help think it might be time to add to these long term holdings and buy more stuff like ETF's and Mutual Funds. This is not for speculation but for long term investing so my choices will be based on what I think will do well over the next 5 to 10 years.

I gave up market timing years ago so I'm still on the sidelines. The old adage of "never catch a falling knife" is good wisdom in times like this. The only way you enter the market bottom is through luck.

A buying opportunity of a lifetime is looming on the horizon.

comments

The Contrarian Case for Getting Active

Right before the New Year I posted an article on Medium titled "Is Passive Investing Going to Kill Us?" It centers around one particular chart where the amount of money flowing into passive investing is staggering.

While I'm a big fan of Passive Investing and I've been riding its success, I can't help but wonder if I was just plain lucky. I know that markets love to correct imbalances but the question is when? Perhaps it might be prudent to think of active strategies again.

Enter Python

I've been using the heck out of Python lately and I discovered a Forex library (it's V20 compatible) that lets me connect to Oanda easily. I did some more research and found a simple momentum trading bot in about 100 lines of python. Of course, this blog post was old and it didn't work out of the box. On top of that it used a deprecated library to connect to Oanda. Luckily I was able to find a brave soul that did a lot of the updates to get it 90% of the way there.

I got the sucker up and running and wouldn't you know it, it sucks. It loses a money when I trade it using a 'paper trading' account. When you think about it, this is the right way of doing it. Test it out using a paper trading account and see how it performs.

Trading Bot Building Process

A customer of mine suggested reading "Advances in Financial Machine Learning" by Marcos Lopez de Prado. It's quite a heavy read but Marcos shares A TON of good stuff in there. Most importantly in my opinion is how to build these trading bots or systems starting in Chapter 1.

It all starts with the Data Curators, the ones that pull in all the tick data and other stuff. They're the ones that augment, compile, aggregate, and curate the data for downstream use. This is a crucial step, if this is not done well, your models will suffer.

Next it's the Feature Analysts. They're the ones that try to extract interesting features from the curated data set. This is also a crucial step because in my experience, good features can make you and bad features can break you.

The third step is where the Strategists come in, they are the ones that are responsible for taking the Data and Features and devising a strategy to use in the markets. When they've come up with a model, they pass this off to the next group, the Back Testers. The Back Testers do just that, they take the new strategy and test it in various market conditions to see if it actually produces alpha.

If the new strategy produces alpha, then the Back Testers move this model over to the Deployment Team. This team is responsible for putting it into production, whether it uses CPU or GPU power, how it's called, etc. The Deployment Team is also responsible for taking this strategy OUT of production once the market has figured out this strategy and you're no longer making money with it.

The last step is Portfolio Oversight. This is where the back tested and deployed strategy is carefully monitored. First from a 'paper trading' implementation, then to live trading. This is where it should start producing returns and where it gets taken out if the returns start faltering.

The book is full of more great information but as I wrote above, it's not for the feint hearted. It's invaluable IMHO if you want to build Trading Bots in a serious manner.

The Python Code

Without much further ado, here's my cobbled together Momentum Trading Bot. Note, the code is not elegant as I'm still working through stuff and it's very simplistic. Works with Python 3.6+ and you'll need to add an account.txt file (the account number from Oanda) and a token.txt file (the V20 API token from Oanda).

#!/usr/bin/env python
# coding: utf-8

# In[1]:


import json
import oandapyV20 as opy
import oandapyV20.endpoints.instruments as instruments
from oandapyV20.contrib.factories import InstrumentsCandlesFactory

import pandas as pd
from pandas.io.json import json_normalize

from oandapyV20.exceptions import V20Error, StreamTerminated
from oandapyV20.endpoints.transactions import TransactionsStream
from oandapyV20.endpoints.pricing import PricingStream
from oandapyV20.contrib.requests import TrailingStopLossOrderRequest

import datetime
from dateutil import parser

import numpy as np


# In[2]:


def exampleAuth():
    accountID, token = None, None
    with open("./oanda_account/account.txt") as I:
        accountID = I.read().strip()
    with open("./oanda_account/token.txt") as I:
        token = I.read().strip()
    return accountID, token


# In[3]:


instrument = "AUD_USD"

#Set time functions to offset chart
today = datetime.datetime.today()
two_years_ago = today - datetime.timedelta(days=720)

current_time = datetime.datetime.now()
twentyfour_hours_ago = current_time - datetime.timedelta(days=2)

print (current_time)
print (twentyfour_hours_ago)


# In[4]:


#Create time parameter for Oanada call
ct = current_time.strftime("%Y-%m-%dT%H:%M:%SZ")
tf = twentyfour_hours_ago.strftime("%Y-%m-%dT%H:%M:%SZ")


# In[5]:


#Connect to tokens
accountID, access_token = exampleAuth()
client = opy.API(access_token=access_token)


# In[6]:


# The v20 api handles from times a little differently - be careful of the timezone
params={"from": tf,
        "to": ct,
        "granularity":'M1',
        "price":'A'}
r = instruments.InstrumentsCandles(instrument=instrument,params=params)
#Do not use client from above
data = client.request(r)
results= [{"time":x['time'],"closeAsk":float(x['ask']['c'])} for x in data['candles']]
df = pd.DataFrame(results).set_index('time')

df.index = pd.DatetimeIndex(df.index)

df.info()
df.head()


# In[7]:


df['returns'] = np.log(df['closeAsk'] / df['closeAsk'].shift(1))

cols = []

for momentum in [15, 30, 60, 120]:
    col = 'position_%s' % momentum
    df[col] = np.sign(df['returns'].rolling(momentum).mean())
    cols.append(col)


# In[8]:


get_ipython().run_line_magic('matplotlib', 'inline')
import seaborn as sns; sns.set()

strats = ['returns']

for col in cols:
    strat = 'strategy_%s' % col.split('_')[1] 
    df[strat] = df[col].shift(1) * df['returns']
    strats.append(strat)


# In[9]:


df[strats].dropna().cumsum().apply(np.exp).plot()


# In[10]:


from oandapyV20.endpoints.pricing import PricingStream
import oandapyV20.endpoints.orders as orders
from oandapyV20.contrib.requests import MarketOrderRequest
from oandapyV20.exceptions import V20Error, StreamTerminated
import oandapyV20.endpoints.trades as trades
from oandapyV20.contrib.requests import TrailingStopLossOrderRequest

class MomentumTrader(PricingStream): 
    def __init__(self, momentum, *args, **kwargs): 
        PricingStream.__init__(self, *args, **kwargs)
        self.ticks = 0 
        self.position = 0
        self.df = pd.DataFrame()
        self.momentum = momentum
        self.units = 1000
        self.connected = False
        #self.client = API(access_token=config['oanda']['access_token'])
        self.client = opy.API(access_token=access_token)

    def create_order(self, units):
        #order = orders.OrderCreate(accountID=config['oanda']['account_id'], data=MarketOrderRequest(instrument="EUR_USD", units=units).data)
        order = orders.OrderCreate(accountID=accountID, data=MarketOrderRequest(instrument=instrument, units=units).data)
        response = self.client.request(order)
        print('\t', response)

        #create a stop might need it's own fuction and called under the trading stragety part
        #stp = pd.Series(response, name='stop')
        #stp_id = stp.orderFillTransaction.get('tradeOpened').get('tradeID')
        #print ('\t The tradeID is ', stp_id)
        #stp_vwap = (stp.orderFillTransaction.get('fullVWAP') - 0.00010
        #print ('\t The stop loss value is ', stp_vwap)
        #stp_order = orders.OrderCreate(accountID=accountID, data=StopLossOrderRequest(tradeID=stp_id, price=stp_vwap))
        #response_stp_order = self.client.request(stp_order)

        #create a trailing stop
        #This below is for a trailing stop that works but the distance is key, this should be set for breakouts
        #tsl = pd.Series(response, name='junk')
        #tsl_id = tsl.orderFillTransaction.get('tradeOpened').get('tradeID')
        #print('The trade ID is: ', tsl_id)
        #tsl_order = orders.OrderCreate(accountID=accountID, data=TrailingStopLossOrderRequest(tradeID=tsl_id, distance=5).data)
        #response_tsl = self.client.request(tsl_order)
        #print('\t', response_tsl)


    def on_success(self, data):
        self.ticks += 1
        print("ticks=",self.ticks)
        # print(self.ticks, end=', ')

        # appends the new tick data to the DataFrame object
        self.df = self.df.append(pd.DataFrame([{'time': data['time'],'closeoutAsk':data['closeoutAsk']}],
                                 index=[data["time"]]))
        # transforms the time information to a DatetimeIndex object
        self.df.index = pd.DatetimeIndex(self.df["time"])

        # Convert items back to numeric (Why, OANDA, why are you returning strings?)
        self.df['closeoutAsk'] = pd.to_numeric(self.df["closeoutAsk"],errors='ignore')

        # resamples the data set to a new, homogeneous interval, set this from '5s' to '1m'
        dfr = self.df.resample('60s').last().bfill()

        #print ('\t this is the dfr', dfr)

        # calculates the log returns
        dfr['returns'] = np.log(dfr['closeoutAsk'] / dfr['closeoutAsk'].shift(1))

        #print('/t returns: ', dfr['returns'])

        # derives the positioning according to the momentum strategy
        dfr['position'] = np.sign(dfr['returns'].rolling(self.momentum).mean())

        print("position=",dfr['position'].iloc[-1])

        if dfr['position'].iloc[-1] == 1:
            print("go long")
            if self.position == 0:
                self.create_order(self.units)
            elif self.position == -1:
                self.create_order(self.units * 2)
            self.position = 1

        elif dfr['position'].iloc[-1] == -1:
            print("go short")
            if self.position == 0:
                self.create_order(-self.units)
            elif self.position == 1:
                self.create_order(-self.units * 2)
            self.position = -1

        if self.ticks == 25000:
            print("close out the position")
            if self.position == 1:
                self.create_order(-self.units)
            elif self.position == -1:
                self.create_order(self.units)
            self.disconnect()

    def disconnect(self):
        self.connected=False

    def rates(self, account_id, instruments, **params):
        self.connected = True
        params = params or {}
        ignore_heartbeat = None
        if "ignore_heartbeat" in params:
            ignore_heartbeat = params['ignore_heartbeat']
        while self.connected:
            response = self.client.request(self)
            for tick in response:
                if not self.connected:
                    break
                if not (ignore_heartbeat and tick["type"]=="HEARTBEAT"):
                    print(tick)
                    self.on_success(tick)


# In[11]:


# Set momentum to be the number of previous 60 second intervals to calculate against
# For two hours, momentum = 120. For 15 minutes, set to 15
mt = MomentumTrader(momentum=15,accountID=accountID,params={'instruments': instrument})
print (mt)


# In[12]:


mt.rates(account_id=accountID, instruments=instrument, ignore_heartbeat=True)


# In[ ]:





# In[ ]:





# In[ ]:





# In[ ]:

comments

Updated Forex Charts with Bokeh

Just updating my past post on autogenerating support and resistance lines for the EURUSD. I've updated the charts to use Bokeh, a nicer and interactive set of plots. You can zoom in and see the candles at various price levels. I still need to do more labeling work on the charts as I learn how to use the Bokeh library. The thing that's hanging me up right now is how to correctly label the horizontal support and resistance lines (aka as Spans in Bokeh) with the actual value. The other thing I need to do is add a legend. Red means resistance and Green means support.

The charts work on 2 years of data with a 20 day look back period for generating the support and resistance lines. In the future I want to optimize the look back period using some other method. What method? I don't know but that's on the back burner until I figure out how to generate a single webpage with the charts loaded into them.

In case you want to see what gets autogenerated every Saturday morning, you can click on the EUR_USD, USD_JPY, and GBP_USD currency pairs. If there any other ones you want to see, drop me a comment below and I'll add them.

UPDATE

I added the expected returns for a momentum startegy to each currency pair chart. The idea is to see if you can be profitable with momentum trades over 15, 30, 60, and 120 days. Some results are very interesting. I have a Momentum Trading Bot all built and ready to go. I just need to set up my Oanda account correctly and then I'll start 'practice' trade it.

I also added some stockcharts for MSFT, GOOG, AMZN, DATA, AAPL and NVDA. These get updated daily and they're for a 15 day time period. Same as above, green color is support and red is resistance.

Some Crypto Currency support for BTC and XRP. Still a work in progress!

comments

Morgan Stanley Layoffs, VTI keeps climbing

Yesterday Morgan Stanley announced a 2% reduction in workforce across the entire organization. It's citing an "uncertain global environment." That's a code word for "recession" if you ask me.

The job cuts at the investment bank, the world’s biggest equities trading firm and a leading mergers advisor, will hit technology and operations roles hardest, said the people, who declined to be named. New York-based Morgan Stanley had 60,532 employees as of Sept. 30. via CNBC

Or it could just be they don't want to pay all those bonuses. Either way, you don't lay off in good times. You usually hire to keep the party going. It's when the party is winding down that you start kicking people out.

That said, Vanguard's Total Market Index (VTI) is still charging higher. There's a bit of a top forming in the daily chart but I suspect the party will continue.

VTI Weekly Chart, 12/09/2019

“As long as there is still room for pushing the market interest rate down further, the chances are reasonably good that the boom continues, and that the bust will be adjourned into the future... via MarketWatch

Of course, the market is still going up so it will continue to go up. Until it doesn't. Usually I'd be scared of all this "market going higher" and "bust will be adjourned into the future" talk, but I'm not. The market's going to do what it's going to do and not a moment sooner! I tried market timing and all that jazz, only to realize that doing less = more gains for me. Strange how that works, but it appears to work just fine.

Granted, I don't have any holdings in VTI (maybe one day when I consolidate all my retirement accounts) but it is an impressive ETF. Especially if you look at the expense ratio. It's only 0.03%!

VTI Expense Ratio, December 2019

If I were to invest in this ETF I would split up my money into equal parts and dollar cost average in. Keep your transactions costs and expenses low. If you can't, then ditch the ETF for the VTSMX mutual fund where it probably won't cost you anything to cost average in or reinvest dividends. Passive Investing remains King in my book.

comments

Neural Market Trends is the online home of Thomas Ott.