HN 日本語サマリー

← 一覧へ戻る
プログラミング

銀行Pythonのオーラルヒストリー(2021年)

An oral history of Bank Python (2021) (calpaterson.com)

149 pointsby tosh59 コメント

要約

この記事は、「バンクPython」と呼ばれる、大手投資銀行内で使用されているPythonエコシステムの独自のフォークについて解説しています。一般的なPythonとは大きく異なり、グローバルなPythonオブジェクトデータベース「Barbara」や、金融商品の価値評価における依存関係を管理する有向非巡回グラフシステム「Dagger」などが組み込まれています。これらのシステムは、複雑な金融商品の評価や取引データの管理に特化しており、何千人もの人々が日常的に利用していますが、その実態はほとんど外部に知られていない、非常に特殊な世界を紹介しています。

全文翻訳

銀行Pythonのオーラルヒストリー 2021年11月\n大手投資銀行で使われるPythonの奇妙な世界\nハイファイナンスは異国であり、彼らは物事を異なるやり方で行います。\n今日は、一般にはあまり知られていない、私が「バンクPython」と呼ぶソフトウェアシステムのグループを、鍵穴から覗いてみましょう。バンクPythonの実装は、実質的に、大手投資銀行の多く(すべてではありませんが)で使用されている、Pythonエコシステム全体のプロプライエタリなフォークです。バンクPythonは、ほとんどの人が知っていて愛用している(あるいは嫌っている)一般的な、あるいはごく普通のPythonとはかなり異なります。何千人もの人々がこれらのシステム上で、いや、むしろ「内部で」働いていますが、それらに関する情報は公開ウェブ上にはほとんどありません。私が会話の中でバンクPythonについて説明しようとすると、人々はしばしば私の話を、目がぎょろぎょろした狂人のたわごとだと片付けてきました。あまりにも馬鹿げているように聞こえるからです。ここでは、「ミネルヴァ」と呼ばれる架空の、合成された、想像上のバンクPythonシステムについて議論します。サブシステムの名前は変更されており、正確を期すよう努めますが、いくつかの詳細については様式化する必要があるでしょうし、もちろん、私はすべての詳細を知っているわけではありません。奇妙な間違いを犯す可能性もあります。大まかな内容は把握できていることを願います。\n\n「バーバラ、偉大なキーバリューストア」\nミネルヴァについて最初に知るべきことは、それがPythonオブジェクトのグローバルデータベース上に構築されていることです。\n```python\nimport barbara\n# open a connection to the default database "ring"\ndb = barbara.open()\n# pull out some bond\nmy_gilt = db["/Instruments/UKGILT201510yZXhhbXBsZQ=="]\n# calculate the current value of the bond (according to\n# the bank's modellers)\ncurrent_value: float = my_gilt.value()\n```\nバーバラは、階層的なキー空間を持つシンプルなキーバリューストアです。ピクルとzipだけで作られており、実にシンプルです。バーバラには複数の「リング」、つまり名前空間がありますが、デフォルトのリングはほぼ単一の、銀行全体のグローバルなオブジェクトデータベースです。デフォルトのリングから、取引データ、金融商品データ(上記のとおり)、市場データなどを引き出すことができます。日々のデータの大半はバーバラから取得されます。アプリケーションもまた、内部状態をバーバラに保存することが一般的で、データクラスを非常にシンプルなロックやトランザクション(もしあれば)だけで直接書き込んだり読み出したりします。ミネルヴァのスクリプトにはファイルシステムが利用できず、スクリプトが取得するわずかなデータもバーバラに格納する必要があります。\n内部的には、バーバラのノードは、DynamoやBigTableのように、リング内で書き込みをレプリケートします。`barbara.open()`を呼び出すと、デフォルトリングの最も近い稼働中のインスタンスに接続します。その単一インスタンス内での読み書きは強力に一貫しています。他のインスタンスからの読み書きは迅速に現れますが、即座ではありません。一貫性が重要であれば、常に特定のインスタンスに接続するようにするだけです。これは、必要でなければ推奨されない慣行です。バーバラは驚くほど堅牢であり、おそらくそのシンプルさのためでしょう。完全な障害は極めて稀であり、機能低下の状態はわずかに一般的であるだけです。\n\nデフォルトリングからのパスの例:\nパス 記述\n`/Instruments` 金融商品(債券、株式など)のディレクトリ\n`/Deals` 取引(発生した取引)のディレクトリ\n`/FX` 外国為替部門の汎用エリア\n`/Equities/XLON/VODA/` Vodaphones株に関連するもののディレクトリ\n`/MIFID2/TR/20180103/01` 特定のビジネスプロセスからの中間オブジェクト\n\nバーバラにはいくつかの「オーバーレイ」機能もあります。\n```python\n# connect to multiple rings: keys are 'overlaid' in order of\n# the provided ring names\ndb = barbara.open("middleoffice;ficc;default")\n# get /Etc/Something from the 'middleoffice' ring if it exists there,\n# otherwise try 'ficc' and finally the default ring\nsome_obj = db["/Etc/Something"]\n```\nリングをスタックでリストアップすることができ、各読み込みは最初のリングを試し、もしキーがそこに存在しない場合は2番目のリングを試し、次に3番目のリングを試すといった具合です。書き込みは、常に最初のリングに行くか、またはそのキーがすでに存在する最上位のリングに行くか(表示されていない構成によって決定されます)のいずれかです。バーバラを使用しないいくつかの良い理由があります。データセットが大きい場合は、他の場所、おそらく従来のSQLデータベースやkdb+を検討するのが良いかもしれません。圧縮されたバーバラオブジェクトサイズのソフトリミットは約16MBです。圧縮されたピクルはすでにかなり小さいので、これは実際にはかなり大きなサイズです。バーバラはオブジェクト属性のセカンダリインデックスを備えていますが、セカンダリインデックスがプログラムの非常に重要な部分である場合は、他の場所を検討するのも良いでしょう。\n\n「ダガー、金融商品の有向非巡回グラフ」\n投資銀行が行う重要なことの一つは、金融商品、いわゆる「資産価格設定」の価値を見積もることです。例えば、債券は、それを所有することで得られるすべての金銭から、発行体の破産リスクのために少し割り引いたものとして評価されます。債券はおそらく(概念的には!)最も単純な商品であり、より大きな関心を集めるのは、クレジット・デフォルト・スワップ、金利スワップ、実物商品の合成バージョンなどの他の「デリバティブ」金融商品の評価です。これらはすべて「原資産」に基づいていますが、支払い方が異なります。デリバティブがどのように評価されるかの詳細は重要ではありません。ただし、多くの詳細と多くのデリバティブがあることは言及しておきます。金融商品間の依存関係は、有向非巡回グラフを形成します。いくつかのデリバティブ金融商品の階層の例は次のようになります。\n一部の金融商品は、他の商品からその価値を派生させます。これにより、それらはデリバティブとなります。デリバティブのデリバティブも存在し、一部のデリバティブは複数の原資産からその価値を派生させます。ダガーはミネルヴァのサブシステムであり、これらのデータ依存関係を整理するのに役立ちます。次のようなクラスを記述します。\n```python\nclass CreditDefaultSwap(Instrument):\n """A credit default swap pays some money when a bond goes into default"""\n def __init__(self, bond: Bond):\n super().__init__(underliers=[bond])\n self.bond = bond\n def value(self) -> float:\n # return the (cached) valuation, according to some\n # asset pricing model\n return ...\n```\nダガーは、原資産のグラフのエッジを追跡し、原資産の価値が変更されたときに、バーバラ内のデリバティブを自動的に再評価します。ある企業に関する悪いニュースが発表され、格付け機関が信用格付けを格下げした場合、債券部門の誰かがダガーを介して関連する債券オブジェクトを更新し、ダガーは影響を受けるすべてを自動的に再評価します。これは、何百もの他のデリバティブ商品を意味する可能性があります。信用格下げはかなり刺激的です。\n個々の商品はポジションに構成されます。ポジションクラスは次のようなものです。\n```python\nclass Position:\n """A position is an instrument and how many of it"""\n def __init__(self, inst: Instrument, quantity: float):\n self.inst = inst\n self.quantity = quantity\n def value(self) -> float:\n # return the (cached) valuation, which basically is\n # self.inst.value() * self.quantity\n return ...\n```\n繰り返しますが、ポジションもまた評価できるものであり、その内容物の価値が変化すると、その価値も変化します。また、ダガーによって自動的に再評価されます。そして、ポジションのセットは「ブック」と呼ばれます。これは金融業界で非常に多義的な言葉ですが、この文脈では単にポジションのセットです。\n```python\nclass Book:\n """A book is a set of positions"""\n def __init__(self, contents: Set[Valuable]):\n # the type Valuable is a "protocol" in python terms,\n # or an "interface" in java terms - anything\n # with value()\n self.contents = contents\n def value(self) -> float:\n # again, return the (cached) valuation, which is more\n # or less: sum(p.value() for p in self.contents)\n return ...\n```\nブックは他のブックを含むことができます。最も小さな債券デスクから銀行全体の単一のブックまで、銀行全体にわたるネストされたブックの階層が存在します。銀行を評価するには、次を実行します。\n```python\n# this is the top level book for the whole bank which\n# recursively contains everything else in the whole bank\nbank = db["/Books/BigBankPlc"]\n# this prints the valuat\n```