惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
Microsoft Azure Blog
Microsoft Azure Blog
MongoDB | Blog
MongoDB | Blog
小众软件
小众软件
Apple Machine Learning Research
Apple Machine Learning Research
O
OpenAI News
酷 壳 – CoolShell
酷 壳 – CoolShell
The GitHub Blog
The GitHub Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
博客园 - 聂微东
Engineering at Meta
Engineering at Meta
W
WeLiveSecurity
Hacker News: Ask HN
Hacker News: Ask HN
大猫的无限游戏
大猫的无限游戏
Vercel News
Vercel News
D
Docker
F
Full Disclosure
AI
AI
罗磊的独立博客
博客园 - 【当耐特】
U
Unit 42
S
SegmentFault 最新的问题
Stack Overflow Blog
Stack Overflow Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
P
Palo Alto Networks Blog
博客园_首页
H
Help Net Security
量子位
月光博客
月光博客
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
博客园 - 司徒正美
F
Fortinet All Blogs
D
DataBreaches.Net
B
Blog RSS Feed
Webroot Blog
Webroot Blog
TaoSecurity Blog
TaoSecurity Blog
S
Secure Thoughts
爱范儿
爱范儿
I
InfoQ
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Attack and Defense Labs
Attack and Defense Labs
Application and Cybersecurity Blog
Application and Cybersecurity Blog
C
CERT Recently Published Vulnerability Notes
Martin Fowler
Martin Fowler
Blog — PlanetScale
Blog — PlanetScale
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
S
Securelist

Hacker News

Introducing Claude Opus 4.7 Qwen Studio The Future of Everything is Lies, I Guess: Where Do We Go From Here? GitHub - SeanFDZ/macmind: Single-layer transformer in HyperTalk for the classic Macintosh Show HN: Agent-cache – Multi-tier LLM/tool/session caching for Valkey and Redis Moving a large-scale metrics pipeline from StatsD to OpenTelemetry / Prometheus GitHub - Nightmare-Eclipse/RedSun: The Red Sun vulnerability repository GitHub - SethPyle376/hiraeth: Local AWS emulator focused on fast integration testing, with SQS support, SQLite-backed state, and a debug-friendly web UI. GitHub - macOS26/Agent: Any AI, replaces Claude Code, Cursor, OpenClaw. Over 18 LLM providers (Claude, OpenAI, Gemini, Ollama, Zai, HF, Qwen) wired into a native Mac app that writes code, builds Xcode projects, bumps versions, manages git, automates Safari, use AppleScript, JS or Accessibility, extend Agent! w/ MCP Servers, run tasks from your iPhone via Messages. YouTube now lets you turn off Shorts I Made a Terminal Pager Burgers | マクドナルド公式 Commands — HackerNews CLI documentation ChatGPT for Excel PiCore - Raspberry Pi Port of Tiny Core Linux Live Nation illegally monopolized ticketing market, jury finds Google Broke Its Promise to Me. Now ICE Has My Data. Founding Engineer at Adaptional | Y Combinator CRISPR takes important step toward silencing Down syndrome’s extra chromosome GitHub - saffron-health/libretto: The AI toolkit for building reliable browser automations US v. Heppner (S.D.N.Y. 2026) no attorney-client privilege for AI chats [pdf] Unexpected €54k billing spike in 13 hours: Firebase browser key without API restrictions used for Gemini requests Retrofitting JIT Compilers into C Interpreters IPv6 – Google The Accursèd Alphabetical Clock Cybersecurity Looks Like Proof of Work Now Fragments: April 14 Cal.com Goes Closed Source: Why AI Security Is Forcing Our Decision | Cal.com - Scheduling Software for Online Bookings Laravel raised money and now injects ads directly into your agent When moving fast, talking is the first thing to break Too much Discussion of the XOR swap trick – Heather Cafe Introduction to Spherical Harmonics for Graphics Programmers The Grand Line Building a Z-Machine in the worst possible language High-Level Rust: Getting 80% of the Benefits with 20% of the Pain GitHub - duguyue100/midnight-captain: Inspired by Midnight Commander, tailored to my taste. How to build a `git diff` driver · Jamie Tanna | Software Engineer Center for Responsible, Decentralized Intelligence at Berkeley The Local Universe’s Expansion Rate Is Clearer Than Ever, but Still Doesn’t Add Up - A new synthesis of astronomical measurements confirms a persistent mismatch that could point to physics beyond current models The air throughout our homes is infused with microplastics. But there are things you can do to breathe less of them The disturbing white paper Red Hat is trying to erase from the internet – OSnews The Future of Everything is Lies, I Guess: Annoyances ‘Abhorrent’: the inside story of the Polymarket gamblers betting millions on war Productive procrastination — Max van IJsselmuiden maps, territory and LMs 447 Terabytes per Square Centimetre at Zero Retention Energy: Non-Volatile Memory at the Atomic Scale on Fluorographane Show HN: Pardonned.com – A searchable database of US Pardons 20 Years on AWS and Never Not My Job The Seasons are Wrong Artemis II crew splashes down near San Diego after historic moon mission We gave an AI a 3 year retail lease in SF and asked it to make a profit | Andon Labs How a dancer with ALS used brainwaves to perform live On filing the corners off my MacBooks Installing every* Firefox extension OpenClaw’s memory is unreliable, and you don’t know when it will break Steve Blank Nowhere Is Safe Chimpanzees in Uganda locked in vicious 'civil war', say researchers watgo - a WebAssembly Toolkit for Go linux/Documentation/process/coding-assistants.rst at master · torvalds/linux GitHub - callumlocke/json-formatter: Makes JSON easy to read. Founding Product Engineer at Bild AI | Y Combinator A compelling title that is cryptic enough to get you to take action on it GitHub - Keychron/Keychron-Keyboards-Hardware-Design: Industrial design files for Keychron keyboards and mice. 100+ models with CAD assets in STEP, DXF, DWG, and PDF. Source-available, with commercial use allowed for original compatible accessories within the license terms. [ANNOUNCE] WireGuardNT v0.11 and WireGuard for Windows v0.6 Released 1D-Chess Helium Is Hard to Replace Cooperative Vectors Introduction | Evolve Keeping a Postgres queue healthy — PlanetScale Our response to the Axios developer tool compromise Do Americans read print books, e-books or audiobooks more? The Zettelkasten Method in Obsidian: A Practical Setup Guide Artemis II Is Competency Porn and We Are Starving For It WeakC4 Flight Viz — Cockpit View A Mexican surveillance giant you’ve never heard of is now watching the U.S. border Surelock: Deadlock-Free Mutexes for Rust RISC-V 101 – what is it and what does it mean for Canonical? | Ubuntu The Problem That Built an Industry How Much Linear Memory Access Is Enough? | Solidean Investigating Split Locks on x86-64 Simplest hash functions Sybilproof reputation mechanisms (2005) [pdf] What is a property? How Complex is my Code? Static code analysis in Kotlin — tools overview Toffoli gates are all you need PGLite evangelism dcmake: a new CMake debugger UI Clojure on Fennel part one: Persistent Data Structures Fragments: April 2 Python Release Python install manager 26.1 The Life and Death of the Book Review - Liberties Introducing Database Traffic Control — PlanetScale Bitcoin miners are losing $19,000 on every BTC produced as difficulty drops 7.8% God sleeps in the minerals Building slogbox Apple Silicon and Virtual Machines: Beating the 2 VM Limit Who was “Not Even Wrong” first? Pokemon Evolution Vs Darwinian Evolution The APL Programming Language Source Code
An oral history of Bank Python
Cal Paterson · 2026-06-26 · via Hacker News

The strange world of Python, as used by big investment banks

an image of Canary Wharf as seen from a residential area
High finance is a foreign country; they do things differently there

Today will I take you through the keyhole to look at a group of software systems not well known to the public, which I call "Bank Python". Bank Python implementations are effectively proprietary forks of the entire Python ecosystem which are in use at many (but not all) of the biggest investment banks. Bank Python differs considerably from the common, or garden-variety Python that most people know and love (or hate).

Thousands of people work on - or rather, inside - these systems but there is not a lot about them on the public web. When I've tried to explain Bank Python in conversations people have often dismissed what I've said as the ravings of a swivel-eyed loon. It all just sounds too bonkers.

I will discuss a fictional, amalgamated, imaginary Bank Python system called "Minerva". The names of subsystems will be changed and though I'll try to be accurate I will have to stylise some details and - of course: I don't know every single detail. I might even make the odd mistake. Hopefully I get the broad strokes.

Barbara, the great key value store

The first thing to know about Minerva is that it is built on a global database of Python objects.

import barbara

# open a connection to the default database "ring"
db = barbara.open()

# pull out some bond
my_gilt = db["/Instruments/UKGILT201510yZXhhbXBsZQ=="]

# calculate the current value of the bond (according to
# the bank's modellers)
current_value: float = my_gilt.value()

Barbara is a simple key value store with a hierarchical key space. It's brutally simple: made just from pickle and zip.

Barbara has multiple "rings", or namespaces, but the default ring is more or less a single, global, object database for the entire bank. From the default ring you can pull out trade data, instrument data (as above), market data and so on. A huge fraction, the majority, of data used day-to-day comes out of Barbara.

Applications also commonly store their internal state in Barbara - writing dataclasses straight in and out with only very simple locking and transactions (if any). There is no filesystem available to Minerva scripts and the little bits of data that scripts pick up has to be put into Barbara.

Internally, Barbara nodes replicate writes within their rings, a bit like how Dynamo and BigTable work. When you call barbara.open() it connects to the nearest working instance of the default ring. Within that single instance reads and writes are strongly consistent. Reads and writes from other instances turn up quickly, but not straight away. If consistency matters you simply ensure that you are always connecting to a specific instance - a practice which is discouraged if not necessary. Barbara is surprisingly robust, probably because it is so simple. Outright failures are exceptionally rare and degraded states only a little more common.

Some example paths from the default ring:

Path Description
/Instruments Directory for financial instruments (bonds, stocks, etc)
/Deals Directory for Deals (trades that happened)
/FX Foreign exchange divisions' general area
/Equities/XLON/VODA/ Directory for things to do with Vodaphones shar es
/MIFID2/TR/20180103/01 Intermediate object from some business process

Barbara also has some "overlay" features:

# connect to multiple rings: keys are 'overlaid' in order of
# the provided ring names
db = barbara.open("middleoffice;ficc;default")

# get /Etc/Something from the 'middleoffice' ring if it exists there,
# otherwise try 'ficc' and finally the default ring
some_obj = db["/Etc/Something"]

You can list rings in a stack and then each read will try the first ring, and then, if the key is absent there, it will try the second ring, then the third and so on. Writes can either always go to the first ring or to the uppermost ring where that key already exists (determined by configuration that I have not shown).

There are some good reasons not to use Barbara. If your dataset is large it may be a good idea to look elsewhere - perhaps a traditional SQL database or kdb+. The soft limit on (compressed) Barbara object sizes is about 16MB. Zipped pickles are pretty small already so this is actually quite a large size. Barbara does feature secondary indices on object attributes but if secondary indices are a very important part of your program, it is also a good idea to look elsewhere.

Dagger, a directed, acyclic graph of financial instruments

One important thing that investment banks do is estimate the value of financial instruments - "asset pricing". For example a bond is valued as all the money that you'll get for owning it, discounted a bit for the danger of the issuer of the bond going bust. Bonds are probably (conceptually!) the simplest instrument going and of much greater interest is the valuation of other, "derivative", financial instruments, such as credit default swaps, interest rate swaps, and synthetic versions of real instruments. These are all based on an "underlying" instrument but pay out differently somehow.

The specifics of how derivatives are valued does not matter, except to say that there are both a lot of specifics and a lot of derivatives. The dependencies between instruments forms a directed, acyclic graph. An example hierarchy for some derivative financial instruments might look like this:

diagram of a tree of financial instruments

Some financial instruments derive their value from others. That makes them derivatives. You can get derivatives of derivatives and some derivatives derive their value from multiple underliers.

Dagger is a subsystem in Minerva which serves to help keep these data dependencies straight. You write a class like so:

class CreditDefaultSwap(Instrument):
    """A credit default swap pays some money when a bond goes into
    default"""

    def __init__(self, bond: Bond):
        super().__init__(underliers=[bond])
        self.bond = bond

    def value(self) -> float:
        # return the (cached) valuation, according to some
        # asset pricing model
        return ...

Dagger tracks the edges in the graph of underlying instruments and automatically reprices derivatives in Barbara when the value of the underlying instruments changes. If some bad news about a company is published and a credit agency downgrades their credit rating then someone in bonds will update the relevant Bond object via Dagger and Dagger will automatically revalue everything that is affected. That might mean hundreds of other derivative instruments. Credit downgrades can be rather exciting.

Individual instruments are composed into positions. The Position class looks a bit like this:

class Position:
    """A position is an instrument and how many of it"""
    def __init__(self, inst: Instrument, quantity: float):
        self.inst = inst
        self.quantity = quantity

    def value(self) -> float:
        # return the (cached) valuation, which basically is
        # self.inst.value() * self.quantity
        return ...

Again, note that a position is something you can also value. It is also something whose value changes when the value of things it contains changes. It it also automatically revalued by Dagger.

And a set of positions is called a "book" which is an immensely overloaded word in finance but in this context is just a set of positions:

class Book:
    """A book is a set of positions"""
    def __init__(self, contents: Set[Valuable]):
        # the type Valuable is a "protocol" in python terms,
        # or an "interface" in java terms - anything
        # with value()
        self.contents = contents

    def value(self) -> float:
        # again, return the (cached) valuation, which is more
        # or less: sum(p.value() for p in self.contents)
        return ...

Books can contain other books. There is a hierarchy of nested books all the way up the bank from the smallest bond desk to a single book for the entire bank. To value the bank you would execute:

# this is the top level book for the whole bank which
# recursively contains everything else in the whole bank
bank = db["/Books/BigBankPlc"]

# this prints the valuation of the whole bank
print(bank.value())

That's the dream anyway. In reality the CFO probably uses a different system to generate the accounts. Valuations of subsidiary books are still well used though.

If you understand excel you will be starting to recognise similarities. In Excel, spreadsheets cells are also updated based on their dependencies, also as a directed acyclic graph. Dagger allows people to put their Excel-style modelling calculations into Python, write tests for them, control their versioning without having to mess around with files like CDS-OF-CDS EURO DESK 20180103 Final (final) (2).xlsx. Dagger is a key technology to get financial models out of Excel, into a programming language and under tests and version control.

Dagger doesn't just handle valuations. It also handles the various "risk metrics" that banks use to try to keep a handle on how exposed they are to various bad things that might happen. For example, Dagger makes it relatively easy to find all positions on, say, Compu-Global-Hyper-Mega-Net Plc, which is rumoured to be going bust. That's counting all options, futures, credit instruments and all of it "netted out" to find the complete position on that company for the whole bank. Never again be surprised by your exposure to dodgy subprime lenders!

Walpole, a bank-wide job runner

I've said so far that a lot of data is stored in Barbara. Time to drop a bit of a bombshell: the source code is in Barbara too, not on disk. Remain composed. It's kept in a special Barbara ring called sourcecode.

Not keeping the source code on the filesystem breaks a lot of assumptions. How does such a program run? The answer is Walpole, the bankwide job runner. Walpole is a general purpose runner of jobs, like a mega Jenkins combined with a mega systemd.

As with many things in Minerva, Walpole is not deployed per-team: there is but one, single, bankwide instance. Walpole is suitable for both long lived-services as well as periodic jobs and is even used for builds. Periodic jobs come up a lot in banks: there are many, many, many end of day or weekly jobs to run to update data, check things, send email digests, etc.

Walpole does all the usual stuff you need to run your software. It can restart your software if it crashes and sends out alerts if it keeps crashing. It stores logs. It understands dependencies between jobs (much like systemd does) so if the job that generates the data your job needs fails, you job doesn't even try starting up but instead fires more alerts.

One real advantage is that Walpole considerably lowers the bar for getting your stuff deployed. Anyone can put a job into Walpole - you need only a small ini-style config file explaining what time to run your script, where your main function is and your entire application is deployed with no further negotiation.

This is a big deal because negotiating anything in large bank is an exercise in frustration: lead times on hardware can be measured in months. Getting people to agree with you takes of course much longer than that.

One of the great drawbacks of "Cloud Native Computing" as it now exists is that it's really, really complicated. It is often more complicated than the old, non-cloud, sort of computing. In order to deploy your app outside of Minerva you now need to know something about k8s, or Cloud Formation, or Terraform. This is a skillset so distinct from that of a normal programmer (let alone a financial modeller) that there is no overlap. Conversely, anyone can work out an ini-file.

MnTable, the ubiquitous table library

I always feel that it's a shame that programming languages rarely, if ever, come with a built-in table datastructure. Programmers have an unfortunate tendency to gravitate towards hash tables - particularly in Python and Javascript where they are used to such extent that it is hard to find anything which is not made out of hash tables.

Hash tables have some serious drawbacks. First, most implementations are in-memory only and sit sparsely there, which makes it a pain in the bum to work even with medium sized data sets; a problem Python programs very commonly run into in practice. More importantly they require you to know your access patterns up front and they really had better be by a single primary key.

Tables are the reverse: they are memory-dense and easy to spool to and from disk. They can use b-tree indices to allow efficient access by any route; so you never end up having to invert your dictionary in the middle of your program just so that you can access by something other than the key. They can support bulk operations and can make use of lazy evaluation.

In open source land the popular library for this is pandas but pandas has some serious drawbacks:

  1. It did not exist when Minerva was originally implemented
  2. It is less efficient than you might hope, particularly with memory
  3. It's not brilliant with datasets larger than memory
  4. (Arguably) it has a baroque API

Instead of pandas there is a proprietary table library in Minerva: MnTable.

# make a new table with three columns of the types provided
t1 = mntable.Table([('counterparty', str),
                    ('instrument', str),
                    ('quantity', float)])

# put some stuff in the table (in place, tables are
# immutable by default)
t1.extend(
    [
        ['Cleon Partners', 'xlon:voda', 1200.0],
        ['Cleon Partners', 'xlon:spd', 1200.0],
        ['Blackpebble', 'xlon:voda', 1200.0],
    ],
    in_place=True)

# return a new table (without changing the original)
# that only includes vodafone.  this is lazy and
# won't get evaluated until you look at it
t1.restrict(instrument='xlon:voda')

MnTable gets used everywhere in Bank Python. Some implementations are lumps of C++ (not atypical of financial software) and some are thin veneers over sqlite3. There are many, many programs which start with an MnTable, apply some list of operations to it and then forward the resulting table somewhere else.

This is convenient as data is everywhere in banks and most of it is "medium" sized: in the gigabytes range. A lot is talked about high-frequency traders but the majority of financiers are not looking at tick level or frankly even intra-day level data. "Medium-sized" is big enough that you cannot create an object for every row but not so big that you are going to need some distributed compute cluster thingy.

A measure of the pain

It would be wrong to imply that working with any financial software is pure and untrammelled joy. Minerva is no different.

New starters take an exceptionally long time to get up to speed - and that's if they don't resign in fit of pique as soon as they see the special, mandatory, in-house IDE (as I nearly did). Even months in, new starters are still learning quite fundamental new things: there is a lot that is different.

Over time the divergence between Bank Python and Open Source Python grows. Technology churns on both sides, much faster outside than in of course, but they do not get closer. The rest of the world is not going to adopt any of Minerva's ideas, not least because they've never heard of them. Minerva is also not adopting many of the ideas from the outside. There is an uncharitable view (sometimes expressed internally too) that Minerva as a whole is a grand exercise in NIH syndrome.

By nature, Minerva is holistic and all encompassing. That's great if you're inside but if you're outside, interacting with Minerva is a pain. Occasionally a non-Minerva developer would ask me how he might read some specific piece of data out of Barbara. I would tell him that the best way would be to use the Minerva source code to do that. Ok, he would reply, maybe he could get away with adding a Python script to a cronjob to do that - could I help him get the code? That's easy, I would reply: just read it out of Barbara.

I can just about understand why Minerva has its own IDE - no other IDEs work if you keep your source files in a giant global database. What I can't understand is why it contains its own web framework. Investment banks have a one-way approach to open source software: (some of) it can come in, but none of it can go out. The github profiles of the bulge bracket investment banks are anaemic compared to those of comparably sized companies in different industries. This highly proprietary attitude has remained even as the Volcker Rule has forced nearly all of the proprietary trading out of investment banks. It is a curse.

It could be that the biggest disadvantage is professional. Every year you spend in the Minerva monoculture the skills you need interact with normal software atrophy. By the time I left I had pretty much forgotten how to wrestle pip and virtualenv into shape (essential skills for normal Python). When everything is in the same repo and all code is just an import away, software packaging just does not not come up.

What makes it different

I haven't covered everything that's in a typical Bank Python implementation. For example, I've skipped over things like:

  • the proprietary timeseries data-structure
  • the "vouch" system for getting your changes into prod
  • time travel in Dagger
  • the semi-bespoke (non-git) version control system
  • the Prolog-based permission system
  • replay-oriented financial message buses
  • existential ennui arising from prolonged exposure to Windows 7 and MS Outlook 2010

You'll just have to use your imagination.

That said, I hope that I've given a view of the most important central parts: Barbara, Dagger, Walpole and MnTable. Of those four subsystems, three pertain to data. (The other can be seen as a database of jobs.)

One of the slightly odd things about Minerva is that a lot of it is "data-first", rather than "code-first". This is odd because the majority of software engineering is the reverse. For example, in object oriented design the aim is to organise the program around "classes", which are coherent groupings of behaviour (ie: code), the data is often simply along for the ride. Writing programs with MnTable is different: you group the data into tables and then the code lives separately. These two lenses for organising computations are at the heart of the object relational impedance mismatch which has caused such grief. The force is out of balance: many more programmers can design decent object-oriented classes than can bring a set of tables into third normal form. This is a large part of the reason that that annoying impedance mismatch keeps coming up.

The other unusual thing about Minerva is that it opts, in many cases, to have one big something rather than many small somethings. One big codebase. One big database. One big job runner. Clubbing it all together removes a lot of accidental complexity: you already have a language runtime (and the version in prod is the same as on your computer), a basic database and a place for your code to run before you even start. That means it's possible to sit down, write a script and get it running in prod within the hour, which is a big deal.

Minerva is obviously heavily influenced by the technological path dependency of the financial sector, which is another way of saying: there is a lot of MS Excel. Any new software solution is going to be compared with MS Excel and if the result is unfavourable people will often just use continue to use Excel instead. Many, many technologists have taken one look at an existing workflow of spreadsheets, reacted with performative disgust, and proposed the trifecta of microservices, Kubernetes and something called a "service mesh".

This kind of Big Enterprise technology however takes away that basic agency of those Excel users, who no longer understand the business process they run and now have to negotiate with ludicrous technology dweebs for each software change. The previous pliability of the spreadsheets has been completely lost. Using simple Python functions, in a source controlled system, is a better middle ground than the modern-day equivalent of J2EE. Financiers are able to learn Python, and while they may never be amazing at it they can contribute to a much higher level and even make their own changes and get them deployed.

Crib ideas from existing systems

One thing I regret about software as a field is how little time is spent learning from existing systems and judging what they did well, or badly. There are only a small number of books discussing, in detail, real systems that exist.

Even when the public details of systems are available they can still be strangely understudied. Email has been around a long time: it predates the internet by a decade. And in that time it has not changed enormously fast and is still mostly the same as it was in the 80s. Despite that, a lot of programmers are still a hazy about what happens when you click "send". Some of them, I'm sure, will keep trying to "disrupt" email regardless.

This is a shame as foreign systems, like foreign countries, can be mind expanding when experienced firsthand. Their customs can differ so enormously from yours that it can lead you to rethink your own practices. But when you just hear it second hand, it can sound like nonsense.

I once described Minerva's "vouch" system, briefly, to another programmer who had never seen it. I explained that when you had a code change, you just had to convince any one of the code owners for the file in question to sign it off. If the change was very urgent, they might sign off your change sight unseen, based on your reputation alone. As soon as they clicked that "vouch" button - bang - your new change was in prod: after all, there is no such thing as a deployment step when your code is stored in a database. Disbelieving me, he asked who in the world would trust such a bank. The answer is a lot of people. They are a very big bank. You have certainly heard of them.


Contact/etc


Other notes

If you're curious to try an MnTable-style table library, my friend Sal released a pure-python, API compatible, version called eztable.

I've mentioned that programmers are far too dismissive of MS Excel. You can achieve a awful lot with Excel: more, even, than some programmers can achieve without it. There exist trading systems in "tier one" investment banks where the way that trades are executed is by clicking on special cells in certain special xlsx files.

Even I would accept that that is too far but if you don't already know Excel it is one of the highest value things you can learn. For programmers the best way to find out what you are missing is Joel Spolsky's overview talk, aimed directly at programmers. If you decide to take the red pill after that, I'm told that Coursera's Excel Skills for Business Specialisation is excellent.

One of things that tends to boggle programmer brains is while most software dealing with money uses multiple-precision numbers to make sure the pennies are accurate, financial modelling uses floats instead. This is because clients generally do not ring up about pennies.

I've mentioned Barbara overlays. They also work for source code. You can tell Walpole to mount your own ring in front of sourcecode when it's importing code for a job and then you can push source files to that instead of getting them vouched into sourcecode. All manner of crazy, bananas, tutti frutti hacks lie down this dark path. Do it, but only a little.