Neural Market Trends

Current Status: Self Isolating

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.


Joining the Indie Web

I don't remember how I found it but I learned about the Indie web from this blog post. The Indie Web is a movement to reclaim your authorship and blog from the clutches of corporations. It's not a move back to the 'good ol' days' rather a way of putting your data back into your hands. In other words, don't be the product.

As a Data Scientist, I process lots of data every day. I use whatever we collect or is available from Kaggle datasets to build demos and POCs. I can get A LOT done by doing that. Imagine if you were a Facebook Data Scientist and was able to collect all the data that your users post everyday, for free. Wouldn't you monetize it? Sure you get to use the platform for free because all your friends are on it but you end up buying more crap in the long run because some FB Data Scientist has optimized a model from your data and 1000's of of other peoples.

This is why the Indie Web resonated with me. I'm going to reclaim my data and control. So this week I cut the cord with Google Analytics and Disqus. I'll extract my comments from Disqus and try to port them over somehow (static generators don't do comments very well), but I'm going to start keeping my data right here. I'll have to cut ties with TinyLetter too, I haven't figured out a replacement yet.


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.


Python Forex Trading Bot

I have had some time to continue on my Python Forex Trading Bot now that we're all self isolating. This is purely for educational purposes because when I run this sucker, it loses money. Not so much anymore but it's not profitable. The reason why I say 'educational purposes' is that coding is not my first choice of career and I teach myself as I go along. Coding's been very profitable in other parts of my life and I use it to get $hit done.

I now understand the concept of Classes, which is great because it makes pieces of code very 'pluggable.' Originally I thought I could write a set of functions in the MomentumTrader class that would serve as my Stop and Trailing Stop orders. I did do that only to find out that I was creating those orders AFTER the trade and when the Bot would try to close out or add to the position (as it does because it's a mean reversion strategy) it would sometimes crash. This led me to find a set classes in the API called onFill. This eliminated the need for me to create the order first and THEN add in a stop or trailing stop. I was able to do it once the trade was filled. The moral of the story, you should really understand your API classes.

Overall the API extended by Feite is quite robust and powerful, but it's still very hard to make any money with this thing. Although I've been whining about getting active again, the reality is that the long term wins.

I'll continue to test this over the course of the next few weeks using an Oanda Practice Account but I think I'm going to write a new class that best mimics my current Forex trading style instead. I use the Daily chart, trade pairs where I make $ from the carry trade, and do a long term trend play. That's the beauty of Forex, you can see some great long trends if you zoom out.

My discretionary trading system does have some flaws. I usually get the entry wrong and have to place a second trade to 'scale in.' It's something I don't like doing because it means more risk. I also need to work on proper risk management as well. Right now I don't use stops and I routinely take on 200 pip swings. This has worked out for me because 99% of the time I trade the EURUSD pair, which has been in a long downward trend. I usually make a short entry, then the price turns against me and goes higher, then I place another short entry where the price stabilizes. I think I've been very lucky until now and my trading metrics and expectancy are positive. Still, I feel like I leave a lot to chance and I'd like to size my position accordingly, make better entries, and use better risk management.

Current Python Forex Trading Bot

So here's the latest incarnation of the Bot. I spent some time clean it up and adding in a trailingstop onfill function.

#Install Py Package from:

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

import pandas as pd
from 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
def exampleAuth():
    accountID, token = None, None
    with open("./oanda_account/account.txt") as I:
        accountID =
    with open("./oanda_account/token.txt") as I:
        token =
    return accountID, token
instrument = "EUR_USD"

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

current_time =

twentyfour_hours_ago = current_time - datetime.timedelta(hours=12)
print (current_time)
print (twentyfour_hours_ago)
#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")
#Connect to tokens
accountID, access_token = exampleAuth()
client = opy.API(access_token=access_token)
params={"from": tf,
        "to": ct,
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)
from oandapyV20.endpoints.pricing import PricingStream
import oandapyV20.endpoints.orders as orders
from oandapyV20.contrib.requests import MarketOrderRequest, TrailingStopLossDetails, TakeProfitDetails
from oandapyV20.exceptions import V20Error, StreamTerminated
import oandapyV20.endpoints.trades as trades

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 = opy.API(access_token=access_token)

    def create_order(self, units):
        #You can write a custom distance value here, so distance = some calculation

        trailingStopLossOnFill = TrailingStopLossDetails(distance=0.0005)

        order = orders.OrderCreate(accountID=accountID, 
        response = self.client.request(order)
        print('\t', response)

    def on_success(self, data):
        self.ticks += 1
        # 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']}],

        #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()

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

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


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

            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:

            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:
            elif self.position == -1:

    def disconnect(self):

    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:
                if not (ignore_heartbeat and tick["type"]=="HEARTBEAT"):
# Set momentum to be the number of previous 5 second intervals to calculate against

mt = MomentumTrader(momentum=60,accountID=accountID,params={'instruments': instrument})
print (mt)
mt.rates(account_id=accountID, instruments=instrument, ignore_heartbeat=True)


A Personal Commentary from my Newsletter

My regular blog posting is suffering because I'm busy writing a weekly newsletter instead. I share links that I find interesting and have recently added my personal commentary, which I'm reposting below. Consider this a 'teaser' of what you get if you subscribe to it.

Personal Commentary

I'm super lucky to have a career where I can work from home and travel. When I'm not traveling to client sites, I'm working from home hosting virtual meetings, coding, or just doing normal work stuff. Slack keeps me connected to my coworkers and I do make it point to go into the office once a week if possible.

One day at home, I overheard a newscast that spoke about how South Korea was grappling with the Covid-19 outbreak. They had mentioned that the majority of people and even school children have been moved to a virtual platform. Students stay home but continue their studies. Workers log in and do their work via video conferencing and email. I was reminded by how similar this is to my work situation.

Then the newscaster exclaimed how this remote arrangement is really making people rethink the whole 'commute into work, sit in a cubicle, work, and commute home' process. On the surface, it does seem really silly to go through that every day. Would all this office space really be needed and could this be a way to reduce greenhouse gas emissions too? I found these questions to be deeply introspective and I think remote work is a really powerful way to leverage talent and 'flip the script' on this work-life balance thing to 'life-work balance.'

That's all great until I watched this PBS News Hour discussion on the workers who can't remote in to work, especially in the United States. The discussion starts at the 11:25 minute mark and talks about how low wage service workers might be adversely affected by being forced to take unpaid sick leave. The statistic they quoted is that 40% of workers are in the low wage service industry. They are the ones that serve your food, drive that Uber, etc. Most of them have no health insurance or are underinsured. This could have a two-fold negative effect by keeping the outbreak going (not getting tested or going to work to earn $) and cause an economic shock as people lose homes and jobs.

Without getting political, something like a Universal Basic Income (UBI) and Basic Healthcare for all Americans would be beneficial here. With UBI you would be able to still pay some of your bills and with the basic healthcare, you might be able to get the care you needed if you were sick. The end effect is that our economy would be more stable and could weather these shocks more easily. Whatever your political leaning is, something needs to be done to stabilize our economy if Covid-19 really gets going in the US.


Neural Market Trends is the online home of Thomas Ott.