openportfolio
openportfolio
すべての口座を一冊の帳簿に。すべての予測を記録に。
オープンソース・セルフホスト型のポートフォリオトラッカー。あらゆる証券会社、年金、ウォレット、銀行口座を単一の純資産に統合し、価格の背後にある投資家の資金フローを保存し、事前に登録した予測をBrierスコアで評価します。プロバイダーのAPIキーはどこにも必要ありません。
ダッシュボードとバックエンドをワンクリックで。同期ワーカーは設計上、お使いのマシン上で動作します。デプロイを参照してください。
スクリーンショットはデモの帳簿を示しています。そこに含まれる数字はすべて架空のものです。
ステータス: プレリリース。 動作し、以下のセットアップも機能します。インターフェースは今後変更される可能性があります。
これは取引ボットではありません。 バックエンドには注文を発注する機能はなく、同梱のアダプターは canPlaceOrders: false を宣言しており、PlaceOrderRequest にはデフォルトのない OrderConfirmation が必要です。このツールが行うのは、集約、監視、そしてスコアリングです。
なぜ
無関係に見えて実は同じ問題である、二つの問題。
ポートフォリオは構造的に分散しています。 ここに証券会社、あそこに年金、ISA、取引所口座、銀行残高、そしてどのAPIも返してくれない保有資産。それらのアプリはそれぞれ数字を表示しますが、どれもあなたの本当の数字を表示しません。だから実際に意思決定を左右する数字、つまり合計、一つの銘柄への集中度、使わない通貨で保有されている割合は、誰も持っていない数字なのです。それらは推定され、その推定は意思決定を避ける方向に甘くなります。
市場コメントは説明責任を負いません。 そして、モデルが何を尋ねても自信満々の方向性のある見解を出すようになった瞬間から、その傾向はさらに強まりました。問題は見解が間違っていることではありません。間違ってもコストがかからず痕跡も残らないため、読む価値のある予測者と、ただ流暢なだけの予測者が、外部からも内部からも区別できないことです。
どちらも簿記の失敗なので、openportfolioはそれらを簿記として扱います。
一つの純資産 | 口座は会場アダプターを通じて単一の基準通貨に統合され、為替レートは換算した行に保存されます。そのためスナップショットは、今日のレートが示す価値ではなく、当時の帳簿の価値を記録します。3つの場所に保有されているポジションは、一つのエクスポージャーです。 |
価格だけでなくフロー | 価格は、誰が買い、誰が売らされたかの結果です。投資家タイプ別の純買い、売買回転率、日付付きの将来イベントのカレンダーは、誰かが思い出したときに導出されるのではなく、第一級の時系列として保存されます。強制売り手はスケジュールに従っており、そのスケジュールは公開されています。参加者クラス別のポジションは、CFTCの週次Commitments of Tradersからキーなしで取得されます。 |
スコア化された実績 | 予測は、確率、期間、そしてそれを確定させる条件とともに事前に登録されます。期間が経過すると、機械で解決可能なものは自動的に解決され、Brierスコアが付けられます。信頼度ダイアグラムが成果物です:あなたが言ったこと、実際に起きたこと、そしてその間のギャップを示します。 |
4つ目のテーブルが、ただ一つの理由で存在します。「発表を待ってから決める」という形の推奨は、口に出した瞬間に消えてしまいます。decisions はそのようなもののキューであり、それぞれにトリガー条件と結果があり、いずれかが変化するまでボードに残り続けます。
Related MCP server: FinChat
プロバイダーAPIキーは不要
帳簿を監視することは、実際に何かが監視している場合にのみ有用です:取引終了後の照合、期間が経過した日に予測を確定すること、3週間前に期限が来ていた先送りされた決定に気づくこと。
従量課金の推論はその用途には不適切です。実行ごとにトークン単位で課金される場合、自律的なチェックはすべて購入になり、運用者のお金を無断で使う製品は、まず許可を求めるか、バッチ処理するか、配給する必要があります。その3つすべてが、自分自身を監視するポートフォリオを、見るために許可を求めるポートフォリオに変えてしまいます。
そこで、すべてのモデル呼び出しは、代わりにあなたがすでにサインインしているエージェントCLI、codex、antigravity、または claude にタスクごとのフォールバック順序でディスパッチされます。このリポジトリにはプロバイダーキーはなく、それを入れるフィールドもありません。それでも実行が無料になるわけではありません:サブスクリプションプランにはレート制限があり、フォールバックチェーンが存在する理由の一部は、あるプロバイダーが他のプロバイダーより先に枯渇するからです。変わるのは制限の種類です。エージェントの作業は支出ではなくクォータと実時間によって制限されるため、1回の呼び出しごとに正当化する必要がありません。
その結果、openportfolioは設計上セルフホストです。あなたのデプロイは、あなたのマシン上で、あなた自身のログインで、あなた自身の口座に対して同期を実行します。
機能
サーフェス | |
純資産 | 口座、残高、会場別・資産クラス別の内訳、単一基準通貨でのスナップショット、キーなしFX |
会場 | 宣言された機能を持つアダプター契約; 上場証券とコイン用のキーなしクォートアダプター、および手動アダプター |
フロー | セッションごと、市場ごと、またはシンボルごとの投資家タイプ別の純買いと売買回転率 |
予測 | 確率、期間、解決基準; 期間満了時の自動解決; Brierスコアと信頼度バケット |
決定 | 先送りされた決定のキュー、トリガー条件と結果付き |
カタリスト | 日付付きの将来イベントとそれが影響する資産 |
監査 | すべての状態変更ミューテーションの追記専用記録、cronが無人で行ったものも含む |
MCP | 25のツールにより、 |
マルチテナンシー | すべてのテーブルがテナントにスコープされ、すべてのインデックスがテナントを先頭に、テナントごとに1つのサービスキー |
クイックスタート
Node 22以上、pnpm、およびConvexアカウントが必要です。無料ティアで十分です。
git clone https://github.com/seonglae/openportfolio.git
cd openportfolio
pnpm install
cp .env.example .env.local
npx convex dev --once # creates the deployment
# create the first book
npx convex env set OPENPORTFOLIO_DEV_TENANT home
npx convex run tenants:create '{"slug":"home","name":"Home","baseCurrency":"GBP"}'
# the UI, then the sync loop
pnpm --filter openportfolio-browser dev # http://localhost:6101
npx tsx sync-worker.mts --once何もリンクしていない状態では、提供可能な会場を登録し、純資産ゼロを記録します。これは正しい動作です。実際の値を得るには、手動の保有ファイルを追加します:
[
{ "accountKey": "isa", "symbol": "VWRL", "assetClass": "etf", "qty": 40, "price": 118.2, "currency": "GBP" },
{ "accountKey": "wallet", "symbol": "BTC", "assetClass": "crypto", "qty": 0.15, "price": 0, "currency": "USD" }
]export OPENPORTFOLIO_MANUAL_HOLDINGS=$PWD/holdings.json
npx convex run accounts:link '{"accountKey":"isa","venue":"manual","kind":"brokerage","label":"ISA","currency":"GBP"}'
npx convex run accounts:link '{"accountKey":"wallet","venue":"manual","kind":"wallet","label":"Wallet","currency":"USD"}'
npx tsx sync-worker.mts --onceファイル内の価格は出発点であり、記録ではありません:ワーカーは資産クラスによってルーティングされるキーなしのソースを通じて、可能なすべての行を再クォートし、GBPに換算して一つの合計を書き込みます。株式、ETF、ファンドはYahooへ、コインはCoinGeckoへ。記録された価格自体が記録である行、つまり年金や不動産は、other クラスに割り当てられ、どのクォートソースにも問い合わせられません。
完全なウォークスルー:openportfolio.app/docs/quickstart
またはデプロイする
このフローは、このリポジトリをあなた自身のGitアカウントにクローンし、Vercel MarketplaceからConvexインテグレーションをインストールし、あなた自身のConvexチームの下にConvexプロジェクトをプロビジョニングし、1つの値だけを尋ね、両方の半分を単一のコマンドでビルドします:
npx convex deploy --cmd-url-env-var-name VITE_CONVEX_URL --cmd 'pnpm --filter openportfolio-browser build'Marketplaceのステップが、これが2クリックではなく1クリックである唯一の理由です:Vercelはインポート中にバックエンドを作成できるため、先に作成しに行く必要がなく、ビルドにデプロイキーを渡します。vercel.json は CONVEX_DEPLOY_KEY でコマンドをガードし、プレーンなブラウザビルドにフォールバックするため、同じファイルが、自分でプロビジョニングしてホストされたページを欲しいというデプロイもカバーします。ガードがなければ、そのケースはビルドに失敗します。
何も尋ねません。サインインにキーは不要です。なぜなら、作成されたばかりのデプロイメント内で実行されるからです:認証はパスワードプロバイダーを使用したConvex Authであり、あなたのデプロイメントが独自のトークンを発行・検証し、サインインがデプロイメントの外に出ることはありません。経路に認証会社はなく、他の場所でアカウントを作成する必要もありません。Convex Authは上流でベータ版であり、それがこの選択の正直なコストです。
次に、Convex側で1つのコマンドを実行して、デプロイメントの署名鍵を生成し、最初のブックを作成します。最初のサインアップがそれを所有します:
npx @convex-dev/auth
npx convex run tenants:create '{"slug":"home","name":"Home","baseCurrency":"GBP"}'サインアップはその後自動的に閉じられます。どのテナントにも属さない呼び出し元は、最初のブックしか作成できないため、公開URLが他人のバックエンドになることはありません。OPENPORTFOLIO_OPEN_SIGNUP=1で再び開きます。
同期ワーカーはこの一部ではなく、そうなることはできません。アダプターを通じてあなたのアカウントを読み取り、モデル作業をあなたがサインインしているエージェントCLIにディスパッチしますが、サーバーレス関数内にはサインイン済みのCLIはありません。デプロイされた側は依然として予測を解決し、Convex自身のcronでスコアリングします。残高を更新したいときにワーカーを実行してください。詳細:Deploying。
Cloudflareボタンはありません。そのボタンはWorkersのみをサポートしており、そのモノレポモードはアプリがサブディレクトリに完全に分離されていることを要求しますが、browser/はそうではありません。
公開する前に
localhostで開いている2つのものがあり、デプロイメントがインターネットから到達可能になる前に閉じる必要があります。
開発テナント。
OPENPORTFOLIO_DEV_TENANTが設定されている間、認証されていない呼び出し元はそのテナントにスコープされます。それを設定解除してください。サインインはすでにあり、設定は不要です。サービスキー。 WorkersとMCPサーバーにはブラウザセッションがないため、キーを提示します。ローカルで生成し、そのハッシュのみを送信してください。
npx @convex-dev/auth # once, generates this deployment's signing keys
npx convex env unset OPENPORTFOLIO_DEV_TENANT
KEY="$(openssl rand -hex 32)"
npx convex run tenants:issueServiceKey "{\"key\":\"$KEY\",\"label\":\"sync-worker\",\"role\":\"member\"}"
echo "OPENPORTFOLIO_SERVICE_KEY=$KEY" >> .env.localマルチテナンシー
1つのデプロイメントが多くのブックを保持します。不変条件は、呼び出し元が自分がどのテナントかを決して言わないことです。
tenantIdは呼び出し元のメンバーシップ行またはサービスキー自身の行から導出されるため、クライアントが別のブックに到達するために設定できる引数はありません。公開APIはtenantSlugを受け入れますが、それは複数のテナントに属する呼び出し元の曖昧さを解消するためだけです。メンバーシップが依然として決定します。別のテナントに属するドキュメントIDは、禁止ではなく欠落として読み取られます。「禁止」は行の存在を確認することになり、それ自体がクロステナント読み取りになるためです。
すべてのインデックスはtenantIdで始まるため、スコープを忘れたクエリはインデックスをまったく使用できません。1つの例外は意図的でマークされています。リゾルバーcronは、テナントなしのインデックスを通じてすべてのブックの期限切れコールをスイープし、まさにその理由からinternalMutationです。どのクライアントからも到達できません。
詳細:openportfolio.app/docs/multi-tenancy
会場アダプター
アダプターは自分ができることを宣言し、それだけを実装します:
type VenueAdapter = {
venue: string;
kind: AccountKind;
capabilities: { canReadBalances: boolean; canReadQuotes: boolean; canPlaceOrders: boolean };
readBalances(request: ReadBalancesRequest): Promise<AdapterBalance[]>;
readQuote(request: ReadQuoteRequest): Promise<AdapterQuote>;
placeOrder?(request: PlaceOrderRequest): Promise<OrderReceipt>;
};4つが同梱されており、いずれもキーは不要です。yahooは、上場されている場所ならどこでも、その上場が取引される通貨で価格を付けます。そのため、米国株、LSE ETF、KRX銘柄のブックは、いずれのアカウントも持たずに最新の状態を保てます。coingeckoはコインの価格を付けます。両方とも残高を拒否します。価格ソースはあなたが何を保有しているかを知らないため、空のリストを返すと「何も保有していない」と読まれるからです。manualはあなたが管理するJSONファイルを読み取ります。これにより、年金や非上場の保有が合計から除外されるのではなく、組み込まれます。csvはブローカー自身のエクスポートを読み取ります。OPENPORTFOLIO_CSV_DIRをフォルダーに向けて、<accountKey>.csvをそこに置きます。列は名前で照合されるため、ほとんどのエクスポートは編集なしで機能し、APIが決してないであろうアカウントもカバーします。
どのソースがどの行の価格を付けるかは、すでにその行にあるアセットクラスによって決定され、どちらかにフォールバックすることはありません。両方とも、間違った証券に対してHTTP 200で応答します。YahooにBTCを尋ねると、約68,000ドルのビットコインではなく、約30ドルのGrayscaleトラストが返され、CoinGeckoには約18セントの価値があるaaplというIDのトークンがあります。合計の間違った数字は、欠落した数字よりも悪いため、どちらのソースにも尋ねるべきでないクラスは、単に再価格設定されません。
キー付きブローカーアダプターは同梱されていません。追加するには、packages/node/src/adapters/にモジュールを書き、ワーカーの環境から資格情報を取得し、defaultRegistry()に登録します。資格情報はワーカープロセスに保持してください。バックエンドもこのリポジトリもそれを見ることはありません。
詳細:openportfolio.app/docs/adapters
要件
Node 22+、pnpm
Convexアカウント(無料ティアで十分)
エージェントワーカーを使用する場合は、サインイン済みのエージェントCLIが少なくとも1つ:
codex、antigravity(agy)、またはclaude他には何もありません。認証はあなた自身のデプロイメントで実行されているConvex Authであるため、サインアップするアイデンティティプロバイダーはありません
開発
pnpm typecheck # every workspace, src and test alike
pnpm test # vitest across packages, convex handlers, browser helpers
# the demo build used for the screenshots and the hosted demo
pnpm --filter openportfolio-browser exec vite build --config vite.demo.config.ts
# the marketing site and docs are static; regenerate the docs pages after editing
python3 site/build-docs.py規約、完全なテナント不変条件、およびこのリポジトリで作業するエージェントCLI向けのメモは、AGENTS.mdにあります。
ライセンス
Apache-2.0。LICENSEを参照してください。
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables AI agents to manage and analyze personal investment portfolios, including fund and stock holdings, net value tracking, XIRR calculations, penetration analysis, and backtesting.Apache 2.0
- FlicenseNot gradedqualityCmaintenanceEnables AI agents to manage personal finances through MCP tools for transaction management, spending analytics, and goal tracking.1
- FlicenseNot gradedqualityBmaintenanceSelf-hosted household finance app for shared expenses, budgets, investments, loans, and zakat, exposing MCP tools for AI agents to manage finances via natural language.3
- FlicenseNot gradedqualityCmaintenanceAn MCP server that exposes personal financial data — transaction ledger, portfolio holdings, live/historical market prices, and quantitative risk metrics — as standardized tools, resources, and prompts, enabling natural language reasoning over real computed numbers.
Related MCP Connectors
Real SEC, 13F, insider, congress & macro data your AI agent can cite. Hosted MCP, 24 tools.
The financial MCP for AI agents - 90+ financial tables, SEC filings, signals, alt-data.
Shared long-term memory vault for AI agents with 20 MCP tools.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/seonglae/openportfolio'
If you have feedback or need assistance with the MCP directory API, please join our Discord server