Automated Technical StockTrading Agent For the Penn-Lehman Automated Trading Project Michael Mallin The Penn-Lehman Automated Trading Project (PLAT) • An investigation of designing and implementing software-based agents to trade in financial markets • Joint effort between the University of Pennsylvania and the Equity Capital Management Group of Lehman Brothers, one of the world’s largest brokerage houses and investment banks • Actualized through the Penn Exchange Simular, a program that can run various types of trading simulations Penn eXchange Server (PXS) • PXS – a trading simulation program that runs on a Linux machine and allows an unbounded number of agents to trade with each other, placing buy and sell orders on a single stock for part or all of a simulated single day of trading • Each agent is a compiled C program that adheres to a specified API • PXS can be executed in one of three modes PXS – Execution Modes • Real-time trading – simulation engine receives buy and sell orders from agents, and also reads in orders in real-time from the Island Electronic Crossing Network (“ECN”) • Historical trading – simulation engine receives buy and sell orders from agents, and also reads in orders from an historical log of a real day’s trading • Agent-only – simulation engine receives buy and sell orders from agents only PLAT – 2004/5 • This year, focus was to run in mode 3, to facilitate more controlled studies of agent performance • So how is a market created? (1) Strategy-Based Agents • Agents designed to trade in an effort to maximize their profits (for an entire single day of trading) (2) “Background” Agents • • • Organizers of the project wrote an assortment of parameterized agents Technically equivalent to strategy-based agents, but serve very different purpose Designed to trade not in an effort to profit, but in an effort to mimic a certain macro market behavior PLAT – Background Agents • Vanilla Background Agent – Reads in numbers from a normal distribution (normal distribution data file given as a parameter) – Numbers represent deltas from top buy/sell order book prices – Takes these parameters: • Volume: number of shares for each order it places • Distance: additional delta to subtract/add to top buy/sell order book prices • Frequency: frequency with which agent places orders, in seconds • Assymetric Background Agent – Same as Vanilla Background Agent but takes two Distance params (buy and sell) What kind of stock-trading agent can you write for PXS? • Automated trading: – A PXS agent is a computer program that makes trading decisions based on an algorithmic approach to reading in specified types of inputs and using them to decide how best to maximize its profit. – This input is the only thing at its disposal, so unlike a human trader, the agent cannot consult any additional sources of information, and it cannot act on soft judgement. • Day trading: – A PXS simulation runs over the course of at most one day; agents are expected to liquidate by the end of the simulation. Therefore no long-term profitability considerations are relevant. • Parameterized strategies: – A large part of an agent’s logic can be provided at run-time in the form of arguments. The shell of the algorithm is hard-coded but many factors can and should be parameterized. What kind of stock-trading agent can you write for PXS? (cont’d) • Single-stock trading: – PXS is – at least for the moment – designed to simulate trading only a single stock. • Technical trading: – This is a widely-used term on Wall Street. The meaning that I intend is that trading decisions are based purely “on the numbers”; the inputs at the agent’s disposal consist essentially of prices and volumes of other agents’ (either programs or real traders, depending on the mode) current and historical orders, and the price history of the simulated stock for the fictional or real trading day. – As such, the agent is precluded from using a vast number of contextual elements that many real-world trading strategies employ, such as fundamental analysis of the company who’s stock is being traded, or news releases, or global economic information. – It is important to note that simply being an automated agent does not rule out using such inputs (a computer agent could parse AP news releases, for example). Real-Time Agent Inputs • PXS provides rich API for accessing buy and sell limit order book information • What is a limit order book? – Limit Order = trader specifies both volume and price of stock (e.g. 1000 shares of MSFT @ $24), and order gets queued in buy or sell book • Order price will be below last price of stock – Market Order = trader need only specify volume (or also a price that is higher/lower than top order in sell/buy book) – When market order arrives, gets executed with top order(s) in opposing book – So: a limit order is guaranteed price but not execution; a market order is guaranteed execution but not price (because books could change before execution) Real-Time Agent Inputs (cont’d) • What is a limit order book? (cont’d) – Two order books – buy and sell – each consisting of list of all limit orders • Buy book in descending order of price • Sell book in ascending order of price • (i.e. by attractiveness to opposing side) • Relatively recent development on Wall Street is automation of order book maintenance and order execution by ECNs • Even more recent is publication (by ECNs) of realtime order book data – this is at the heart of PXS • In agent-only mode, PXS order books consist only of agent orders Technical Implementation • Agent implements its strategy in function called “updateAgentOrder()” • Function called by engine at regular intervals of approximately three seconds for the entire course of the simulation, which runs (at most) from 9:30 to 16:00 – i.e. for 23,400 seconds • So updateAgentOrder() called ~ 7,800 times • Therefore agent does not implement any sort of looping mechanism; each call to updateAgentOrder() is expected to make a local decision, the result of which is to place zero to n orders (potentially a mix of buy and sell) at that moment in time My Agent – High-Level Description • Hybrid of two distinct strategies that it switches between depending on what it considers to be the state of the market – – • At a given time, agent operates in one distinct mode When it switches from one mode to the other, makes clean break from former mode before making switch Modes: 1) Market-making strategy: aims to profit on consistent and directionally neutral oscillation of stock’s price 2) Trend-trading strategy: aims to profit on consistent movement of the stock’s price in one direction, followed by either a flattening of price behavior or a switch to other direction My Agent – Design Motivation 1) Simple market-making strategies did very well in the host of simulations that I ran with the technical agents supplied by PLAT as well as in prior PLAT competitions Simple market-making also made intuitive sense – consistently high volatility of stock in single day 2) But: 3) Compelling to try and further enhance profit-making potential by identifying and exploiting actual price trends if and when they occur • 4) Trend-trading didn’t do that well in some cases (Sherstov and Stone) but seemed that tweaking parameters and controlling when it was run could enhance performance (And thinking about programming different variations on the market-making theme seemed not as interesting to code ) My Agent – updateAgentOrder() updateAgentOrder() begin if (at a designated trading time) if (in strategy-based trading time) tradeBasedOnStrategy() else withdrawOrders() doSingleLiquidation(remainingLiquidationOpps) end My Agent – updateAgentOrder() Explanation: • If function called at calculated point at which agent makes trades (based on interval param given to agent), and current time is still before point at which makes sense to close up its daily position (hard-coded at 15:30 – the day ends at 16:00), agent trades/does not trade based on its strategy • Otherwise, withdraws any of its unmatched orders on the books, and performs single iteration of liquidation – The concept of “single iteration of liquidation” based on liquidation strategy of spreading out liquidation over multiple trades, to avoid placing orders of very large volumes that can have negative effect on price and liquidity – arg remainingLiquidationOpps tells doSingleLiquidation() how many additional times it expects to call it – So doSingleLiquidation() makes single decision but from a more global perspective. My Agent – tradeBasedOnStrategy() tradeBasedOnStrategy() begin read current price P add P to list of prices if (we’ve already built a full list of prices) calculate the price regression slope PS add PS to the list of price regression slopes if (PS is near zero) tradeBasedOnMarketMaking() else if (we’ve already built a full price regression slope list) calculate second regression PSS tradeBasedOnTrend() end My Agent – tradeBasedOnStrategy() Explanation: • Maintains two lists: 1) 2) • • • Local price history over (parameterized) specific interval of time Local history of price regression slopes over (parameterized) specific interval of time Adds latest price and price regression slopes to two lists, shifting out oldest elements in each If price slope is near zero (the concept of “near” is quantified by an epsilon argument given to the agent), agent seeks to profit from “market-neutral” trading via market-making mode Otherwise, agent concludes there is some price trend, and seeks to profit on it via trend-trading mode My Agent – tradeBasedOnMarketMaking() /* N and mmVolume are user-supplied params */ tradeBasedOnMarketMaking(N, mmVolume) begin place buy order just in front of Nth order in buy book for mmVolume shares place sell order just in front of Nth order in sell book for mmVolume shares end My Agent – tradeBasedOnMarketMaking() Explanation: • Simple market-making strategy that always places pair of buy and sell orders – Buy below last price – Sell above the last price • How far below and above is not computed directly from last price, but by stepping just in front of the Nth order in both books – Agent steps exactly in middle of the Nth and the (N-1)th orders – If N = 1, steps in the middle of the 1st order and the last price – (Any order in buy book is <= last price, and any order in sell book is >= last price – either can be equal if only part of that order was just matched.) My Agent – tradeBasedOnTrend() /* pSlope = slope of price regression line pSlopeSlope = slope of price regression slopes line tfVolume is user-supplied param */ tradeBasedOnTrend(pSlope, pSlopeSlope, tfVolume) begin if (pSlope > 0 and pSlopeSlope >= 0) //price rising place buy order in front of 1st order in buy book for tfVolume shares else if (pSlope < 0 and pSlopeSlope <= 0) //price falling place sell order in front of 1st order in sell book for tfVolume shares else //trend reversal withdrawOrders() doSingleLiquidation(1) end My Agent – tradeBasedOnTrend() Explanation: • Buys if price on the rise and sells if on the decline, provided that price “acceleration” is monotonic in the relative direction • If neither case holds, closes out position that it built up based on last trend, seeking to collect its profits • Implicit Assumption (or bug ): Agent never in risk of going immediately from trend trading mode to market making mode without first closing out its position – this is because if the price slope gets to near zero, there must have first been a trend reversal My Agent – doSingleLiquidation() /* remainingLiquidationOpps = remaining number of chances for liquidation */ doSingleLiquidation(remainingLiquidationOpps) begin get current share holdings C if (C < 0) get total number of order shares in sell queue SQ if (-C / remainingLiquidationOpps <= SQ) place buy market order for –C / remainingLiquidationOpps shares else place buy market order for SQ shares else if (C > 0) get total number of order shares in buy queue BQ if (C / remainingLiquidationOpps <= BQ) place sell market order for C / remainingLiquidationOpps shares else place sell market order for BQ shares end My Agent – doSingleLiquidation() Explanation: Examines agent’s current share position • If non-zero, seeks to (wholly or partially) zero it out by placing trades in the opposite direction • Volume in which it places these trades determined by it’s total position vis-à-vis the current size of the opposing order book My Agent – User-Defined Parameters Name Description Default Value interval interval, in seconds, at which agent employs strategy to place/not place orders 10 flat epsilon used to determine what “near zero” means when looking at price regression slope 0 regression length, in seconds, of time interval over which price regression is computed 3,600 (i.e. one hour) price slope regression length length, in seconds, of time interval over which the price slope (i.e. the second) regression is computed 400 price slope epsilon price length My Agent – User-Defined Parameters (cont’d) Name Description Default Value market making strategy volume volume of all orders placed when in market making strategy mode 1,000 market making strategy order book index index of order in buy/sell book that market making strategy steps just ahead of when placing orders volume of all orders placed when in market making strategy mode 2 trend trading strategy volume 1,000 Open Issues / Further Work (besides writing an entirely new agent…) • Partial Liquidation – As explained above, when agent is in trend trading mode and perceives trend reversal, it liquidates, seeking to actualize its profit – Current implementation: attempts to do this in only one order (which is why doSingleLiquidation() called with value of 1 for remainingLiquidationOpps arg) – This simple solution could be dangerous if current position is very long or short Open Issues / Further Work (cont’d) • Partial Liquidation (cont’d) – Another implementation would be to spread liquidation over some interval, similar to way in which end-of-trading-day liquidation is done – Design question then becomes one of determing the length of interval – options include Open Issues / Further Work (cont’d) 1) Use “average length of price trend”, as this is expected amount of time until next trend reversal • • Hard to estimate, but more importantly Inherently flawed, because if your moving from trend A to trend B, and A and B are the same duration, you will (in theory) break even! In fact, using an expected value means that you implicitly “expect” that this will happen! 2) Compute “reasonable” length of time, based on level of current position and on some expectation of length of trend you’re entering • Could look at levels of regression slopes, or use order-book metric like VWAP differentials Open Issues / Further Work (cont’d) • Residual Effect of Switching Strategy Modes – – – – Two possible mode transitions that can occur unbounded times during trading day: (1) from market making to trend trading, or (2) from trend trading to market making Assumption: (2) is not a problem, because price slope won’t go to zero w/out first showing trend reversal (so agent does local liquidation) But (1) can be dirty because no guarantee that all orders placed were matched (which is one of the aims of marketmaking) So if agent does nothing, it can carry non-zero position into next mode Open Issues / Further Work (cont’d) • Residual Effect of Switching Strategy Modes (cont’d) – – – My agent currently allows this – i.e. it does nothing to prevent it Claim: This is sound Proof (sort of): There are two possible cases: 1) Agent is long/short when the switch is about to be made, and the trend is now up/down. Let’s take the long/up case. So the price is on the rise, and the agent must have unmatched sell orders. But these orders should now be matched, as the price is rising! So this seems an impossible situation. 2) Agent is long/short when the switch is about to be made, and trend is now down/up. In either of these two logically equivalent cases, the agent’s unmatched sell/buy orders will remain unmatched. But what is our alternative to leaving them on the books? We could withdraw them, but that is akin to accepting defeat. It is better to leave them, hoping for a future trend reversal that gives us at least a chance of matching the orders. Open Issues / Further Work (cont’d) • Strength/Weakness of Predictive Model – Agent’s understanding of the market based entirely on computing linear regressions of prices and price slopes • Simply an implementation of agent described in Feng, Yu and Stone • They explain in their article that this model produced premature trend reversal signals, leading to premature unwinding – Idea for expanding it: • Incorporate order book-based metric as well, such as order book volume differences between buy and sell order books (see Subramanian) or VWAP • Given agent’s design, this could be purely additive – i.e. the strategies remain the same, but the logic of determing which one to use and when becomes more elaborate Why you should consider writing something for PLAT • The PXS API is very clear and putting new ideas to work is relatively easy • PLAT will continue to have competitions (as soon as their server is replaced) • Algorithmic trading is hot in financial software (especially related to hedge funds) and salaries are high – “Algorithmic Trading Services will even consider sharing all or some of the downside risk for academics / quants who want to become involved with developing extremely high level, complex systems for these markets, and profit from the trading of these systems.” • Lots of AI techniques (e.g. machine learning) are employed • I’ve done a lot of the annoying work