Participation strategy - part 2

This series looks at building a near full-scale application in q and, in the process, tries to answer questions on the amount of code a q application requires, and how that code can be organised so that it is both comprehensible and straightforward to change. The target application is a participation strategy and some of its associated testing framework.

In this installment the "near" tactic is added to the participation strategy. Previously in this series: the "far" execution tactic. Next: market trials.


Looking ahead, here is the same test as in the previous installment, but with both "far" and "near" execution tactics. To get to this stage required eight orders from the user session.

Note how the average prices, avgprx, are now closer to VWAP. A view, benchmarks has been added to the strategy to give a clearer view of how the orders perform against the target participation rate and various prices. Since all the user session orders hit the ask side of the book, performance is skewed for buys and sells: the slippage from VWAP ranges from 1 - 7bps for buys to 32bps for sells.

More testing

Testing multiple execution tactics and multiple orders requires more power tools. The user.q script is now extended to load another script, player.q which can enter a table of orders. Inside a user session, a table can be loaded and each row played every 50 milliseconds with the following statement:

play [`:/kdb/qx/player.csv; 50]

player.q uses the built-in q timer function .z.ts and the timer command system "t" (more often typed as \t on the command line). The play function can accept either a file name (a symbol) or a table: the table is held in the .player context while it is being played.

This script helped discover an overlooked defect with id's in matching within qx.q, fixed in this installment.



The implementation of the "near" tactic closely follows the pattern of far.q, although the rules are slightly simpler. Recall that "near" pegs a single downstream for each upstream order allocation in the control table, controlnear. There are a couple of differences from the specification.

  1. Strictly, the maximum uncommitted quantity that can be placed is leaves less the quantity already on the book, which can be computed from the downstream orders. Otherwise the tactic will overcommit.
  2. As this tactic has a lower priority than the "far" tactic, there seems little merit in placing small orders as it nears completion. So the decision step in the pipeline will place all the remaining uncommmitted quantity when completing.

The amount of decision making now inside the strategy means more instrumentation is needed. near.q uses an "alarm" concept built into participation.q to record significant events in a table, via an upd function of course.


All allocations are made through the upd pattern, passing a list of id's that need to be allocated. Allocations are made in multiples of minqty, as specified. The size of the multiple is currently fixed, likewise the threshold at which further allocations are made. These will be examined in the market trials. One aspect not yet implemented is the transfer of quantity from "near" to "far".

Other changes

As mentioned above, user.q now loads the player script and qx.q has a defect fixed. The other changes are:

All other code can be downloaded through the links in the section below.


This installment has added 30% more lines of code:

Lines of code

The ratio of application code to testing code is now 60:40.

Further reading
2.Further updates, and more q code, can be found at This is a secure site: for browsing the user name is anonymous with password anonymous.