"Alpha Engine" implementation?

Back

Has anyone tried an implementation of The Alpha Engine, the forex strategy described in the paper by this name? I am interested in testing it in QC, and I'm surprised that I don't see any previous mention of it in the community.

This strategy ignores the time component and forms bars based on price movement. It seems very similar to using renko charting, and applying a state machine to make trades (using pyramiding) based on reversals and continuations in the bar series. Considering this, should I start from a blank strategy template or pick some existing template? It seems like is a good use case for a consolidator. As I haven't yet finished the bookcamp and the QC LEAN framework still seems a bit daunting, a little guidance would be much appreciated.

Update Backtest







 
0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


I started coding it up and realized that a consolidator is not a good solution, and instead, it's better / easier to simply store the extremal maximum and extremal minimum, updating with each tick, until the bar is done.

However, it looks like the strategy calls for simultaneous long and short positions (short hedging?), which QC doesn't support, so perhaps options will work for all the short positions.

0

Hi Robert,

This seems like an interesting paper that I could look into adding to the Strategy Library,

Best,
Shile Wen

1

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Hi Shile,

I've been working on implementing the author's charting system they call "Intrinsic Time". Ideally this would be a tool which could employed in any strategy, and that's the objective I'm working towards; reusability. I don't think it's there yet, but here's a starting point. Included are some charts I was able to generate in a research book. Code provided below.

SPY OHLC:

118845_1608680206.jpg

SPY Intrinsic Time (using 3% change delta):

118845_1608680128.jpg

 

I also have a C# implementation, which employs RollingWindow. I wasn't able to use RollingWindow in Python because it won't accept a Python class as the type parameter (is it possible to use a wildcard type, like the `any` type in TypeScript?).

The other challenges I ran into is that I don't see an obvious way to plot the data in a C# research book, and I don't know to wrap and then import my C# classes in a Python research book, which would allow me to implement this entirely in C#, and then test it in a Python research book, plot the results, and then use the C# code directly in a C# algo.

Research Book

qb = QuantBook()
spy = qb.AddEquity("SPY")
days = 360
history = qb.History(qb.Securities.Keys, days, Resolution.Daily)

import pandas as pd
import mplfinance as mpf
from IntrinsicTime import IntrinsicTimeChart

it = IntrinsicTimeChart(0.03, days + 1)

# write every new bar into table struct at IT run-time
new_table = {"Date":[], "Open": [], "High": [], "Low": [], "Close": []}
def writeBarToTable(bar):
new_table["Date"].append(bar.time)
new_table["Low"].append(bar.low)
new_table["High"].append(bar.high)
if bar.direction == 'u':
new_table["Open"].append(bar.low)
new_table["Close"].append(bar.high)
else:
new_table["Open"].append(bar.high)
new_table["Close"].append(bar.low)
it.OnStep = writeBarToTable

# push price history into IT
for index, row in history.iterrows():
bar = TradeBar()
bar.Open = row['open']
bar.High = row['high']
bar.Low = row['low']
bar.Close = row['close']
it.NewCandlestick(index[1], bar)

# plot intrinsic time series
df = pd.DataFrame(new_table)
df.index = df["Date"]
mpf.plot(df, type='candlestick')

# plot historical price as OHLC
spy = history.loc['SPY']
spy.rename(columns={"open": "Open", "high": "High", "low": "Low", "close": "Close", "volume": "Volume"}, inplace=True)
mpf.plot(spy)

 

Intrinsic Time Python Implementation

Note: With full tick data, use the NewPrice method (this is the ideal approach). For OHLC data (which is suboptimal due to loss of resolution), use NewCandlestick. However, note that this method makes a compromise in assuming a particular order for processing the OHLC values per bar, and this may effect your results. If you use 1 second bars, and your percentage change is large enough, I think you won't be impacted by this compromise.

Note: This implementation uses recursion to produce charts without gaps, this is what I understood from the paper as being the intended approach. IOW: Any gaps in real price movement will be filled with bars in the intrinsic time series.

from QuantConnect.Data.Market import TradeBar

class IntrinsicTimeBar:
reversal: False
direction: None
time: None
high: None
low: None

def __init__(self, time, high: float, low: float, direction=None, reversal=False):
self.reversal = reversal
self.direction = direction
self.time = time
self.high = high
self.low = low


class IntrinsicTimeChart:
maxPercentageChange = None
maxLength = None
lengthNow = 0
OnStep = None
upper = None
lower = None

def __init__(self, max_percentage_change: float, length = 2):
self.maxPercentageChange = max_percentage_change
self.maxLength = max(2, length)
self.window = []
self.upper = None
self.lower = None


def __AddBar(self, new_price: float, new_bar: IntrinsicTimeBar):
self.window.insert(0, new_bar)
length = len(self.window)

if length > self.maxLength:
self.window.pop(self.maxLength)
else:
self.lengthNow = length

self.upper = new_price
self.lower = new_price

if self.OnStep:
self.OnStep(new_bar)


def NewCandlestick(self, time, bar: TradeBar):
if self.upper == None:
self.upper = bar.Open
self.lower = bar.Open

avg_level = (self.upper + self.lower) * 0.5
ohlc_order = [
('Open', abs(avg_level - bar.Open)),
('High', abs(avg_level - bar.High)),
('Low', abs(avg_level - bar.Close)),
('Close', abs(avg_level - bar.Close))
]
ohlc_order = [t[0] for t in sorted(ohlc_order, key=lambda t: t[1])]
for prop in ohlc_order:
self.NewPrice(time, getattr(bar, prop))


def NewPrice(self, time, price: float):
self.upper = price if self.upper == None else max(price, self.upper)
self.lower = price if self.lower == None else min(price, self.lower)

allowable_change = (self.upper + self.lower) * 0.5 * self.maxPercentageChange

if self.upper - self.lower < allowable_change:
return

new_level = None
new_bar = IntrinsicTimeBar(time, self.upper, self.lower, direction=None, reversal=False)
possible_high = self.lower + allowable_change
possible_low = self.upper - allowable_change

if price > possible_high:
new_bar.high = new_level = possible_high
new_bar.direction = 'u'
if self.lengthNow > 0 and self.window[0].direction == 'd':
new_bar.reversal = True

elif price < possible_low:
new_bar.low = new_level = possible_low
new_bar.direction = 'd'
if self.lengthNow > 0 and self.window[0].direction == 'u':
new_bar.reversal = True

else:
raise Exception('the impossible has happened')

self.__AddBar(new_level, new_bar)
self.NewPrice(time, price)

 

Just briefly, some assorted thoughts on programming languages on the platform:

I'm completely new to C#, and I'm really not a fan of OOP languages in general. However, the strong type checking in C# makes it much nicer to work with than Python. Sure would be nice if F# would become usable. I'm not really sure why it's an option on the platform, since selecting F# triggers an error saying "invalid language selection". I asked support and they replied that it's marked as beta, but I don't see beta mentioned anywhere in the interface.

 

0

Feedback, critiques, and suggestions are much appreciated. And especially, any help on how to run my C# code in a python notebook, or how to plot charts in a C# notebook.

0

Actually, I spotted a bug in the NewCandlestick method, so I fix that, and posted the updated file as a gist here (which is what I should have done in my earlier reply). Enjoy.

 

0

Hi Robert,

You can use a Python deque to store types not supported by RollingWindows. In addition, we have a GH Issue here for C# plotting, and feel free to subscribe to it to be notified when it's merged.

Best,
Shile Wen

1

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Here's a C# implementation of intrinsic time.

0


Update Backtest





0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Loading...

To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!