Delta in sub-minute time windows
TL;DR
In a previous post the concept of cumulative delta was used as a tool to understand the correlation between order execution (as captured in tick data) and price trends. In this post we try to find patterns that could support trading decisions in delta variations over smaller than 1-minute time windows.
Intro
The conclusion of the previous post was that cumulative delta could explain in large part price trends, as the ones highlighted in Figure 1 below.
From an analysis standpoint it is an interesting result, but may pose challenges supporting trading decisions. For example, if someone was following the delta variation from 13:55 to 13:59, it would see a seesaw of positive and negative values. At 14:00 a large magnitude green bar formed on the delta graph, representing strong buy activity. If that was to be used as input to a trading decision, the conclusion could have been to send a market order to buy, in the assumption that the trend would continue in the next minutes. But as we can see in the graph, from 14:01 to 14:03 there was a reversal, sending the price back to the open level of 14:00.
If the objective was to take advantage of movements similar to the one at 14:00, zooming in at smaller than 1-minute time windows could be of help.
Getting data
The same tick data collected in the previous post will be used here, with the difference on how the aggregation will be done. Instead of calculating the delta on 1-minute time windows, which would represents all the buy and sell trades made between 0 and 59 second of each minute, we use smaller slices, each with a few seconds.
That will be done by splitting the interval into multiples segments of equal length, as in the code below.
def cut_minute(grouped_df: pd.DataFrame, freq: int):
"interval"] = pd.cut(
grouped_df[
grouped_df.second,0, 60, freq=freq, closed="left"),
pd.interval_range(=True,
include_lowest
)return grouped_df
= (
tick_data "year", "month", "day", "hour", "minute"])
tick_data.groupby([apply(cut_minute, freq=5)
.=True)
.reset_index(drop )
The tick_data
variable contains a data frame of the trades around 14:00, with numeric columns to represent year, month, day, hour and minute when each trade took place. By using groupby
on all those variables, the data frame is divided so that the trades in each minute are placed together. By applying the cut_minute
function to each group, an extra column is added to the resulting data frame, which will identify trades that happened in groups of 5 seconds (notice the parameter freq=5
). That is done by the use of pd.cut
over the second
column of each grouped data frame.
The resulting tick_data
should be similar to the following, on which the first two rows represent buy orders executed between seconds 0 and 4 (interval
equal to [0,5)
) and the next four records represent orders executed between seconds 5 and 9 (interval
equal to [5,10)
):
interval
column
Now that trades in each time window have the same interval
category, it is possible to use this column to group the ticks and calculate the delta in these sub-minute windows. At the same time, the values for open, high, low and close can be collected, creating the basis for a visualization. The code below calculates delta and creates the OHLC candles.
def ohlc_delta(volume_df):
"flags"] == TICK_SELL, "volume"] = (
volume_df.loc[volume_df[-1 * volume_df.loc[volume_df["flags"] == TICK_SELL, "volume"]
)
= datetime.datetime(
current_datetime 0],
volume_df.year.unique()[0],
volume_df.month.unique()[0],
volume_df.day.unique()[0],
volume_df.hour.unique()[0],
volume_df.minute.unique()[0].left,
volume_df.interval.unique()[
)
= {
raw_data "datetime": current_datetime,
"open": volume_df.loc[volume_df["last"] > 0]["last"].iloc[0],
"high": volume_df.loc[volume_df["last"] > 0]["last"].max(),
"low": volume_df.loc[volume_df["last"] > 0]["last"].min(),
"close": volume_df.loc[volume_df["last"] > 0]["last"].iloc[-1],
"volume": volume_df.volume.sum(),
}
return pd.DataFrame(raw_data, index=[0])
= (
ohlc_data "year", "month", "day", "hour", "minute", "interval"])
tick_data.groupby([apply(ohlc_delta)
.=True)
.reset_index(drop )
The resulting OHLC raw data with 5-second candles should look like the Figure 3 below:
By using the OHLC raw data as the basis for a visualization, the resulting graph should be similar to Figure 4 below.
High level analysis
In Figure 1 the trades that took place during the minute of 14:00 are shown in the delta bar graph as a single large green bar, indicating an isolated surge in buy activity and its resulting positive delta. Using that information alone to support a trading decision might lead to send a buy order at 14:01, when a downtrend starts, resulting in a loss.
The finer grained information in Figure 4 allows identifying inside minute 14:00 at least two moments of increased buy activity: one between seconds 0 and 4 and another between seconds 40 and 45. With that new insight, a decision to send a buy order around second 40 could take advantage of most of the price movement between $4,158 to $4,162, or 0.1%.
By the way the delta in calculated, the values represent only what happened in each specific time window, with no sense of continuity from the previous periods. That can be seen in the spikes in the delta bar graph, with sudden changes in magnitude and signal. One way to smooth the curve and make it simpler to interpret is to use a rolling sum, as illustrated in Figure 5 below.
The delta bar graph now shows at each moment the rolling sum of delta over 10 seconds; as the candle size is now 2 seconds, that equals to the 5 most recent candles. It is possible to see that the rolling sum crosses the zero line and turns positive around second 40, where the short term price uptrend begins. Noticing zero crossings of delta rolling sum values, whether the price variation at that moment is positive or negative and the relation of delta value and the amount of price change could be use as support data to the trading decisions.
A future post will how to connect to MT5 using Python in order to automate the data collection, the calculation of indicators and the issue of market order using the analysis results above.
The complete source code for this post can be found in this Github Gist.
Disclaimer
Futures and options trading has large potential rewards, but also large potential risk. You must be aware of the risks and be willing to accept them in order to invest in the futures and options markets. Do not trade with money you can not afford to lose. This post is neither a solicitation nor an offer to buy or sell futures or options. No representation is being made that any account will or is likely to achieve profits or losses similar to those discussed. The past performance of any trading system or methodology is not necessarily indicative of future results.
This post is provided for informational and educational purposes only. This material neither is, nor should be construed as an offer, solicitation, or recommendation to buy or sell any securities. Any investment decisions made by the reader through the use of this content is solely based on the reader independent analysis, taking into consideration their financial circumstances and risk tolerance. The author shall not be liable for any errors or for any actions taken in reliance thereon.
The references made to MT5 and AMP Global in this post do not represent a recommendation. I am not affiliated to neither platform, service nor their parent companies.