In 30 seconds
In a CMU lecture, Jane Street’s Ron Minsky explains the firm’s role as a market maker and arbitrageur, then connects its technology choices to correctness, agility and performance. He argues that concise code and static checks help people understand and safely change trading systems. He demonstrates algebraic data types with a trading-instruction example and discusses OCaml’s historical limitations in interfaces, concurrency and libraries. In questions he explains the firm’s gradual adoption and distinguishes his experience-based judgments from controlled evidence.
- 1Market making and inventoryA market maker facilitates trades with buy and sell quotes and seeks to earn the spread. It still faces risk when inventory moves against it.
- 2Speed raises the cost of mistakesAutomated systems can repeat a bad decision rapidly. The faster the loop, the less time a person may have to notice and intervene.
- 3Reading is part of correctnessCritical trading code was reviewed line by line. Minsky emphasizes code as communication between people as well as instructions to machines.
- 4Types support changeA tagged instruction type and exhaustive match let the compiler flag code that misses a newly added cancel-replace case.
- 5Ecosystem gapsAt the time, Minsky saw weaknesses in user interfaces, concurrency tooling, libraries and programming at large scale.
- 6Adoption was gradualAn initial research effort and later experiment expanded over time; the company did not switch every system in one step.
Takeaways
- Market makers provide liquidity by quoting buy and sell prices while managing inventory risk.
- Faster trading raises the stakes of correctness because errors can repeat before a human can intervene.
- Readable code, reduced boilerplate and static checks can make both review and change safer.
- Algebraic data types and exhaustive pattern matching can expose places that must change as a system evolves.
- Language decisions also depend on operational needs, ecosystem limits, recruiting and the team’s existing code.
Read the edited text by chapter
A trading firm chooses OCaml
Minsky introduces Jane Street’s move from mainstream languages to OCaml. He frames the decision in terms of the business and its technical requirements.
When Jane Street began, it used mainstream tools for financial software: Visual Basic behind spreadsheets, C, Java and C++. Over several years, we moved to OCaml as our primary development language. This is a trading firm, not an application naturally linked to the academic fields in which statically typed functional languages first became popular.
We use OCaml because we think it is a good tool for the problems we face, even though those problems were not what the language was invented to solve. To explain that decision, I will first describe our business, then the demands it places on technology, and finally where OCaml fits and where it falls short.
Investors, speculators and market makers
He distinguishes motivations for trading and explains how market makers quote prices, collect spreads and manage inventory risk.
A trading firm makes money by buying and selling securities, but that definition tells you little about its work. It helps to distinguish several idealized motivations for trading. Real participants need not fit neatly into one category, and the categories are not exhaustive.
An investor puts capital at risk in exchange for an expected return. The basic investor need not claim to know which securities are mispriced; buying a diversified index fund is an example of taking broad market exposure without trying to pick winners.
A speculator, by contrast, tries to exploit a view that a security is mispriced. If it looks undervalued, the speculator buys and hopes the market eventually recognizes its value. Being right alone is not enough: the position must become profitable in a useful time if the capital is to be reused.
Suppose you think IBM is worth more than the market believes. Holding it indefinitely might eventually deliver value through dividends, but that ties up your money while other opportunities appear. Speculation may be done by individuals or by professionals such as hedge funds.
A market maker is a professional whose business is facilitating trades. The market maker quotes both a buying price and a higher selling price, aiming to transact repeatedly and earn the spread. A bookie calls a similar gap the vig; a grocery store calls it markup.

A tighter spread offers more attractive prices and can attract more trading volume. Like a grocer, a market maker is not primarily trying to predict where prices will be months from now; the business depends on many transactions, managing inventory and controlling costs.
That does not eliminate price risk. If a grocer buys a shipment of tomatoes and the price falls, competitors may be able to sell more cheaply and the grocer can lose money. A market maker likewise tries to avoid accumulating a position that moves against it.
Arbitrage and Jane Street’s business
A currency example illustrates arbitrage and its relationship to market making. He describes the firm’s proprietary structure and scale at the time.
Arbitrage is another professional activity. Imagine converting dollars to pounds in one market, pounds to yen in another and yen back to dollars in a third. If the cycle leaves you with more dollars than you started with, the prices offer an arbitrage opportunity.
Such opportunities usually disappear because people seek and execute them. Their trades push inconsistent prices toward one another, making the markets more efficient. Market making and arbitrage are closely related where prices of different instruments constrain one another.
For example, if two currency markets are liquid and a third trades infrequently, prices from the liquid markets can help infer a price for the illiquid one. That estimate should inform the market maker’s quotes; otherwise better-informed counterparties can trade against stale prices.
Jane Street is involved in market making and arbitrage, not long-term investing or the sort of speculation that depends on predicting prices years ahead. We may have views on what happens over seconds, minutes or hours, but that is a very different horizon from forecasting years into the future.
At the time of this talk, we describe ourselves as a proprietary trading company with no explicit customers and no outside investors. Liquidity provision does serve investors indirectly: when an index fund trades on behalf of a retirement saver, tighter markets can improve execution, even though neither party identifies the other as a customer.
The firm’s working capital comes from the people who manage it. That structure gives us room to think from first principles about technical choices without an outside customer prescribing the technology. At this point we have about 190 employees in several offices, including roughly 35 people who spend much of their time writing OCaml.
OCaml is not confined to a small research corner: it is a first choice for systems administration, monitoring, trading and research systems. We use other tools too, but its breadth makes the match between the language and our operational requirements important.
Correctness, agility and performance
Trading software must avoid rapidly repeated errors, adapt to changing markets and process data efficiently. Operational complexity makes human time a scarce resource.
The first requirement is correctness. There is no faster way to burn through money than to repeat a bad trading decision in a tight loop. Our systems interact directly with markets, so we have long been afraid of mistakes and put substantial effort into preventing them.
To illustrate the stakes at the time, one to two percent of US domestic equity trades have Jane Street on one side, and hundreds of millions of shares and billions of dollars of nominal value flow through our systems each day. These are not all positions held at once, but a small error repeated many times can still be disastrous.
Speed matters for effective execution, but speed also makes mistakes propagate faster. A tighter loop can make it harder for a human to notice and intervene before damage accumulates. As execution becomes faster, software quality becomes more critical.
Agility is the ability to change code quickly as circumstances change. New ideas from employees require software changes; so do new rules, securities, venues and changes to the behavior of exchanges. The surrounding market is constantly moving underneath our systems.
The market’s evolution illustrates the problem. Minsky describes an earlier era of manual execution and telephone calls on Nasdaq, then the emergence of electronic venues, routing and new regulations. His account is historical, reflecting the market as he described it in this lecture.
Electronic markets, new venues, dark pools and instruments such as ETFs changed what systems needed to understand. Similar changes occur in options and international equities. As systems become more electronic, changes can arrive faster, so the ability to update code efficiently is essential.
Performance is another requirement. Market data arrives at very high rates across many securities, and we need both to react quickly and to store information for later research, modeling and simulation. Minsky describes response times on the order of a millisecond and roughly a terabyte of raw data a day in his contemporary example.
A terabyte a day is not enormous by the standards of the largest scientific or internet systems. But hardware is only part of the cost: the less efficient the software, the more machines and infrastructure people must operate. Human attention is scarce, so throwing hardware at a problem can consume people who could be doing other valuable work.
Readable code and the type system
Minsky explains the firm’s code-review culture and argues that brevity and static types help people reason about programs. Boilerplate makes review and change more difficult.
Our approach to correctness starts with reading code. Before I joined, some of the firm’s principals committed to reading every line of the most critical trading systems before production. They were afraid of software failure, and the people making technology decisions were also the people who had to understand the code.
Code is not merely a way to make a machine do something; it is also a way to express what a system is meant to do to other people. That perspective influenced our choices. A planned move from spreadsheet-backed Visual Basic to an object-oriented system ran into trouble partly because the resulting code was hard to read.
The proposed code was verbose, and readers found layers of dynamic dispatch difficult to follow: when a call appears, which implementation will actually run? I remember finding it hard to answer cleanly. For us, two properties make OCaml attractive for reading: brevity and types.
Concise expression can make code easier to review, provided it remains clear. Renaming every function to two characters would not help. The valuable kind of concision comes from expressing a common pattern once, using tools such as higher-order functions and functors; carefully constrained macros can also help.
Boilerplate is often repeated because the language makes a recurring pattern difficult to express directly. Its low density of interesting information makes it surprisingly hard to review: readers start glossing over what looks familiar, even though small differences still need to be correct.
Reading code involves building an informal argument that it does what you expect. Anything a mechanical checker can establish removes part of that burden. OCaml has many useful features, but I think parametric polymorphism and algebraic data types deliver much of the practical value.
Algebraic data types in a trading protocol
Orders, cancels and cancel-replaces illustrate sum types and exhaustive matches. Compiler warnings can identify places that need updating as the model changes.
An algebraic data type combines product types and sum types. A product groups several values, as a record or C struct does; a sum represents alternatives—this kind of value or that kind. The ability to represent alternatives directly is especially useful in ordinary application code.
Pattern matching adds a convenient way to analyze those alternatives. The compiler can warn when cases are missing, redundant or impossible. An unhandled case matters because a value arriving in that case could cause an exception at runtime.
Consider a simplified exchange protocol. An order has an identifier, price and size; a cancel refers to an existing order by identifier. We can define a tagged instruction type that is either an order or a cancel, then process lists of both as a single stream.

A filter function can take the instruction list and an order ID. It matches each item and compares the appropriate field: the order ID for an order and the referenced ID for a cancel. This is a small example, but it shows how the type and case analysis work together.
Suppose we add a cancel-replace instruction, an atomic request to remove an order and replace it with a new price and size. Once we add that alternative to the instruction type, the compiler can warn that the existing match does not handle it. If we remove an alternative, it can warn about an impossible case.

Those checks help carry an invariant through a codebase as types evolve. They also support refactoring by identifying code that needs attention. The benefit is not automatic in every style: a catch-all branch can silence the warning and leave the code fragile when a new alternative appears.
It is tempting to think of a type system as a separate layer that sometimes rejects a sensible program and sometimes catches an error. To use ML well, you need to treat types as a design tool and actively encode properties you want the compiler to help check.
Performance and ecosystem tradeoffs
He considers the relationship between agility and correctness, then compares performance predictability with a SQL optimizer. He describes historical gaps in OCaml tooling and libraries.
The same properties support agility. When a change is necessary, the key question is how quickly we can gain confidence that the changed system is still correct. Static checks help find affected code, and reducing boilerplate keeps a change from having to be repeated manually in many places.
On performance, ML occupies a useful point in the design space. It is expressive enough for a clean, fairly declarative style while still supporting a relatively straightforward compilation strategy that produces fast code. More expressiveness or more control can each bring tradeoffs.
SQL shows a different tradeoff. It can express some tasks at a very high level, but an optimizer decides how to execute them. A small query change or a change in table size may lead to a different plan and a large performance shift; Minsky says that unpredictability has been a practical problem for the firm.
OCaml’s code generation and garbage collector have worked well for Jane Street, including tuning for low-latency, soft real-time behavior. There are performance weaknesses too, but Minsky’s larger point is that ML offers a productive compromise between expressiveness and performance that engineers can reason about.
There are also real weaknesses in the ecosystem as it stood at the time of the talk. Building user interfaces was painful: available wrappers existed, but Minsky found few strong OCaml-native libraries for industrial interfaces. Some of the firm’s successful interfaces used curses-style text displays.
Concurrency was another issue. The OCaml implementation he describes could support threads for interaction with low-level libraries, but could not run OCaml code physically in parallel on multiple cores in one process. Separate processes communicating by messages were possible, yet high-level tools for doing so effectively were limited.
A small language community can contain excellent people while still having fewer libraries than communities around Java or Perl. Minsky also identifies gaps in package distribution, namespaces and support for programming at large scale. Jane Street already had roughly a million lines of OCaml, so those weaknesses were practical rather than theoretical.
He sees the biggest opportunities for improvement outside the core language. Libraries, interfaces and practical tooling are not always what academic funding rewards. Jane Street’s summer project funds students working with faculty on projects that make functional languages more useful for real applications.
An additional benefit, he says, is recruiting. Attracting strong programmers interested in OCaml was part of the original decision, not merely a pleasant surprise afterward. The firm was still looking for such people when he gave the talk.
Questions on implementations and large systems
The audience asks about Standard ML, compiler strategies and team organization. Minsky explains the shared repository and the limits of language comparisons.
In questions, Minsky distinguishes OCaml from merely an object-oriented extension to ML. It has an object system, but he says Jane Street does not use it. OCaml and Standard ML have different histories and implementations, yet they share more than they differ.
Asked why OCaml rather than Standard ML, he discusses implementation tradeoffs. MLton’s whole-program strategy can make some abstractions cheap, whereas OCaml’s native compiler has a comparatively simple strategy and useful Unix and C integration. He stresses that history also mattered: his Cornell colleague Mark Hayden used OCaml, and Minsky began using it for projects at Jane Street.
He clarifies that OCaml’s native compiler performs some optimizations but is not the aggressive optimizer the name might suggest. Despite a simple approach, its generated code performs well. A whole-program compiler can remove abstraction costs, though an engineer may have to reason about when particular optimizations will occur.
A questioner asks whether functional programming changed the organization of the team. At the firm’s then-current scale, Minsky says, the team kept most code in one shared Mercurial repository. A common snapshot, builds and tests made it easier to verify the system together and make changes that crossed many components.
Being able to see and modify the code across the system gives the team flexibility. A change need not stop at a separately published interface whose implementation is inaccessible. He nevertheless thinks stronger tools for larger-scale programming would be valuable as systems and communities grow.
Another questioner asks whether repetitive code in earlier systems was a design failure or something tied to the language. Minsky cautions that language comparisons are hard to prove: different people wrote the systems at different stages, and the team learned between implementations. His judgment comes from experience rather than a controlled comparison.
He nevertheless finds common functionality easier to factor out in functional code. Higher-order functions make small abstractions relatively lightweight. When abstraction requires more effort, programmers are more likely to copy a template and make small changes, leaving a pattern spread across the codebase.
Minsky distinguishes several ideas associated with object-oriented programming. He values abstraction and interfaces; he considers subtyping useful in some situations but prefers parametric polymorphism as a default. A map over lists, for example, can state precisely that it transforms values of one type into values of another.
He is more critical of inheritance and dynamic dispatch as defaults. In his view they can make it harder to reason about what code will run and can require understanding the implementation being inherited. He notes that object-oriented design literature itself often recommends composition over inheritance.
He does not claim OCaml can express every abstraction perfectly. Language and type-system limits remain, and his comparison is a judgment he cannot prove experimentally. But he thinks lightweight abstraction reduces the effort needed to extract and reuse simple patterns.
Adoption, hiring and alternatives
Minsky discusses recruiting, parallelism and gradual adoption. He concludes with a qualified historical assessment of F# and the cost of switching.
Asked whether using OCaml made him wealthier, Minsky jokes about job security before giving a qualified yes. Recruiting strong programmers was easier, and he believes better technology helped the firm move faster and make more money. He also acknowledges that the factors are hard to separate.
On physical parallelism, he says the firm already uses multiple processors in clusters and trading. Some workloads are naturally parallel, so replicating simple units works well. Better infrastructure would help the community and Jane Street, but the limitation he described does not make parallel computing impossible.
On programming in the large, Minsky wants better packaging, namespaces and development tools, especially clearer error messages. Because much of Jane Street’s software is bespoke and internally maintained, the shortage of external integration is less painful for the firm than it might be elsewhere.
The adoption decision was gradual rather than a meeting to rewrite the company. Minsky initially built his own research environment, including a small cluster, while the firm was largely a Windows shop. Once he stayed, he hired a small team to work on research and trading strategies in OCaml.
The existing spreadsheet systems had been pragmatic initially, but copying and modifying them for each variation was not a sustainable long-term approach. As the team considered the next generation, recruiting for OCaml proved unexpectedly successful: one mailing-list request yielded a strong set of candidates and three hires.
Rather than switch everything at once, Minsky wrote a first version of a system over three months. The team tried it, compared it with the existing system, read the code and expanded its use gradually. He says they expected to teach the language to good programmers rather than require every future hire to know it already.
Asked about F#, Minsky praises its potential to bring functional programming to a wider audience but gives reasons Jane Street was not planning to switch. Its existing million-line OCaml codebase used features that would be expensive to port, and he had concerns about allocation behavior for the symbolic workloads they ran.
He also raises a concern about null values when interoperating with .NET libraries, while explicitly acknowledging uncertainty about some F# details. He had not investigated enough to settle whether its object system could replace OCaml functors for his purposes. These comments describe his assessment at the time, not a current comparison of the languages.
Finally, Minsky says the team was more comfortable with OCaml and Unix for its systems. He gives precise timekeeping on Windows as one historical concern for high-performance trading applications. The choice reflects the team’s accumulated code, environment and needs as well as language features.
More from this channel
15:33EN
1:48:29EN
1:36:37EN
1:05:45EN
1:25:00EN
1:16:29EN