q-finder: 素敵な金融論文と出会いポロリを探求しよう

はじめに
金融や投資に関する学術研究は日々進化していますが、最新の研究論文を効率よく発見する手段は意外と限られています。特に、非専門家が膨大な量の論文から興味のあるものを見つけ出すことは容易ではありません。
そこで私たちは「q-finder」を開発しました。arXivの金融(q-fin)カテゴリの論文を直感的なスワイプインターフェースで閲覧できる、いわゆる「Tinder for Papers」アプリケーションです。このアプリケーションは完全にクライアントサイドで動作し、特別なサーバー構築なしで簡単にデプロイできます。
技術スタック
q-finderの特徴的な技術スタックを紹介します:
- フロントエンド: 純粋なHTML/CSS/JavaScriptによる実装(フレームワークレス)
- データ処理: DuckDB-wasm(ブラウザ上で動作するSQLデータベース)
- データ形式: Apache Parquet(高効率なカラム指向データ形式)
- ストレージ: AWS S3(データホスティング)+ CloudFront(配信)
- 分析: Google Analytics 4(ユーザーインタラクションの追跡)
特筆すべきは、サーバーサイドのデータベースを使わずに完全にクライアント上でSQL処理を実行している点です。DuckDB-wasmによりブラウザ上で数十万件の論文データに対してSQL検索が可能になっています。
主要機能
Tinder風インターフェース
論文カードを右(Like)または左(Skip)にスワイプすることで、自分の興味に合った論文を直感的に分類できます。
// Like機能の実装(抜粋)
function likePaper() {
if (currentIndex >= allPapers.length) return;
const card = document.querySelector('.paper-card');
card.classList.add('swipe-right');
// Get current paper
const paper = allPapers[currentIndex];
// Add to history and track in GA4
gtag('event', 'paper_like', {
'paper_id': paper.id,
'paper_title': typeof paper.title === 'string' ? paper.title : String(paper.title),
'paper_categories': typeof paper.categories === 'string' ? paper.categories : String(paper.categories),
'action': 'like'
});
// Update UI and move to next paper
// ...
}
賢い重複排除と表示最適化
一度評価した論文は表示されなくなり、常に新しい論文が提示されます。この実装には、LocalStorageでの評価履歴保存とSQLクエリでの除外処理を併用しています。
// 評価済み論文の除外(抜粋)
const history = JSON.parse(localStorage.getItem(HISTORY_KEY) || '[]');
const ratedPaperIds = history.map(item => item.id);
// バッチに分けてSQLに巨大なIN句を渡す問題を回避
const batchSize = 1000;
const batches = [];
for (let i = 0; i < ratedPaperIds.length; i += batchSize) {
const batchIds = ratedPaperIds.slice(i, i + batchSize);
batches.push(`CAST(arxiv_id AS VARCHAR) NOT IN ('${batchIds.join("','")}') `);
}
リアルタイムフィルタリング
カテゴリや出版年でフィルタリング可能なため、特定分野の論文だけをターゲットにできます。フィルター変更時は毎回データが再取得され、新しいランダム順序で表示されます。
パワフルな検索機能
別画面の検索ページでは、自然言語による全文検索と結果のページネーション表示を実装。URLパラメータによる検索状態の保存とシェア機能も備えています。
技術的な実装詳細
DuckDB-wasmによるブラウザ内SQL処理
通常、このような検索機能を持つアプリケーションではサーバーサイドデータベースが必要ですが、q-finderはDuckDB-wasmを活用し、すべての処理をブラウザ上で完結させています。
async function initDuckDB() {
// DuckDBの初期化
const JSDELIVR_BUNDLES = duckdb.getJsDelivrBundles();
const bundle = await duckdb.selectBundle(JSDELIVR_BUNDLES);
// Workerの作成と初期化
const worker_url = URL.createObjectURL(
new Blob([`importScripts("${bundle.mainWorker}");`], {type: 'text/javascript'})
);
const worker = new Worker(worker_url);
const db = new duckdb.AsyncDuckDB(new duckdb.ConsoleLogger(), worker);
await db.instantiate(bundle.mainModule, bundle.pthreadWorker);
return db;
}
Parquetファイルを直接クエリできる機能により、数百MBの論文データを高速に検索できます。
インフラストラクチャ
Terraformを使用してAWS上のインフラを構築し、S3とCloudFrontでデプロイを自動化しています。データパイプラインは以下の流れで処理されます:
- arXivのAPIからq-finカテゴリの論文を定期的に取得
- 抽出したデータをJSONLとParquet形式で保存
- S3にアップロードしCloudFrontで配信
- ブラウザ上のDuckDBがデータをダウンロードして処理
パフォーマンス最適化
データローディング
初回ロード時のユーザー体験を最適化するため、次のような工夫を施しています:
- Parquet形式の採用によるデータ転送サイズの大幅削減
- ページロード中の視覚的フィードバック
- 必要に応じたデータのリフレッシュ
レスポンシブUI
スマートフォンからデスクトップまで、さまざまなデバイスサイズに対応するUIデザインを採用。カードスワイプのアニメーションも軽量に実装しています。
データ分析と改善サイクル
Google Analytics 4を活用して、ユーザーの論文評価行動を追跡しています。これにより、最も「いいね」された論文カテゴリや、ユーザーが飽きるまでの平均スワイプ回数などのインサイトが得られます。
// GA4でのイベントトラッキング(抜粋)
gtag('event', 'paper_like', {
'paper_id': paper.id,
'paper_title': paper.title,
'paper_categories': paper.categories,
'action': 'like'
});
直面した課題と解決策
大量データの効率的処理
数万件の論文データをクライアントサイドで効率的に処理するために、以下の手法を採用しました:
- SQLによるデータフィルタリングを最大限活用
- 局所的にメモリ上に保持するデータを最小化
- 評価済み論文のフィルタリングを最適化(バッチ処理)
DuckDBの制約対応
文字列型と日付型の扱いに関する課題を解決しました:
// 日付型への変換例
const yearCondition = `AND (EXTRACT(YEAR FROM CAST(published AS TIMESTAMP)) = ${yearFilter})`;
開発の今後
q-finderは継続的に改善を行っています。今後の計画として:
- 論文の関連度予測アルゴリズムの実装(ユーザーの過去の「いいね」に基づく推薦)
- 複数のソース(arXiv以外)からの論文データの統合
- ユーザー間での「いいね」した論文の共有機能
技術選定の振り返り
フレームワークを使わず、バニラJavaScriptとDuckDB-wasmの組み合わせを選んだ理由は、依存関係の最小化とブラウザ上での高速なクエリ処理の実現です。また、AWS S3+CloudFrontによるインフラは、ほぼサーバーレスで高可用性を確保できる点が魅力でした。
まとめ
q-finderプロジェクトは、学術研究論文の閲覧体験を根本から見直すアプローチを示しています。直感的なUIと高度なデータ処理技術の組み合わせにより、研究者や金融の専門家が効率的に価値ある情報を発見できるようになりました。
https://qfinder.p-hunters.com
興味のある方は、以下のリンクからq-finderを試してみてください:この記事が皆様のプロジェクトに何らかのインスピレーションを与えれば幸いです。質問やフィードバックがありましたら、お気軽にコメントでお知らせください。

ChatGPT Operatorに
Go to the site https://qfinder.p-hunters.com/ and display q-fin papers in a Tinder-style format. Select and like at least 10 papers that are recommended for forex and cryptocurrency bot developers to read. After evaluating, create a table detailing the reasons for liking or skipping each paper, and if liked, assign a score from 0-10.
と指示すれば、為替・仮想通貨botterとして読むべき論文にLikeしてくれ、点数付きで評価結果をまとめてくれる。

5/3 q-finderの開発進捗
GWですね。
q-finderはQuantitative Financeに関するarXiv論文と効率的に出会えるマッチングWebサービスです。この記事では、前回の開発報告以降に追加された主要機能について紹介します。
主な追加機能
1. マイページ機能
ユーザーがLikeまたはSkipした論文を履歴として保存し、簡単に参照できるマイページ機能を実装しました。
マイページの主な特徴:
- Like/Skipごとのフィルタリングタブ
- 論文の状態を視覚的に表示(緑色のボーダー = Like、赤色のボーダー = Skip)
- ページネーション機能で多数の論文を効率的に閲覧可能
- 各論文のメディアコンテンツ数を表示(🎧アイコンと数字)
// 論文カードの例
const paperCard = document.createElement('div');
paperCard.className = `paper-card status-${paper.action}`;
// メディア数のインジケーター表示
const mediaCount = mediaCountMap[paper.id] || 0;
const mediaIndicator = mediaCount > 0 ?
`<span class="media-indicator">(${mediaCount})🎧</span>` : '';
2. ランキング機能
人気のある論文をランキング形式で表示する機能を実装しました。これにより、コミュニティで注目されている論文を簡単に発見できます。
ランキングの主な特徴:
- 「Like」数に基づいた論文のランキング表示
- ユーザー自身の評価状態も合わせて表示(緑/赤のボーダー)
- DuckDBを使用したイベントデータの高速集計
// DuckDBを使ったランキングクエリ
const result = await conn.query(`
SELECT
paper_title,
paper_id,
COUNT(*) as like_count
FROM like_events
WHERE event_name = 'paper_like'
GROUP BY paper_title, paper_id
ORDER BY like_count DESC
LIMIT 5
`);
3. 検索機能の強化
テキスト検索機能を大幅に強化し、より柔軟で高度な論文検索が可能になりました。
検索機能の主な特徴:
- 全文検索(タイトルと要約)
- カテゴリと年によるフィルタリング
- 関連性、日付(新しい順/古い順)によるソート
- 検索結果のハイライト表示
- URL パラメータによる検索状態の保存・共有
- ページネーション機能
// 検索条件の構築例
const searchTerms = query.trim().toLowerCase().split(/\s+/).filter(term => term.length > 1);
const searchConditions = searchTerms.map(term =>
`(LOWER(title) LIKE '%${term}%' OR LOWER(abstract) LIKE '%${term}%')`
).join(' AND ');
4. Loungeリンク機能
「Lounge」機能へのリンクをマイページやランキングページに追加し、論文に関するディスカッションをより簡単に開始できるようになりました。
// ランダムなLoungeフレーズの生成
function getRandomLoungePhrase() {
return LOUNGE_PHRASES[Math.floor(Math.random() * LOUNGE_PHRASES.length)];
}
// Loungeリンクの例
const loungeLink = paper.action === 'like' ?
`<a href="lounge.html#${paper.id}" class="paper-link lounge-link" title="Go to Lounge😍">
<i class="fas fa-headphones"></i> ${getRandomLoungePhrase()}
</a>` : '';
5. PWA対応とプッシュ通知
Progressive Web App(PWA)としての機能を強化し、ホーム画面へのインストールやプッシュ通知をサポートしました。
PWA関連の主な特徴:
- インストール可能なWebアプリケーション
- オフライン対応
- プッシュ通知設定
- キャッシュ管理
// PWA初期化コード
if (window.qFinderPWA) {
qFinderPWA.init();
} else {
console.error('PWAモジュールが読み込まれていません');
}
// プッシュ通知マネージャー初期化
if (window.qFinderPushManager) {
qFinderPushManager.init();
} else {
console.error('プッシュ通知マネージャーが読み込まれていません');
}
技術的な改善点
DuckDB-Wasmの活用
クライアントサイドでのデータ処理にDuckDB-Wasmを採用し、大量の論文データをブラウザ上で高速に処理できるようになりました。
// DuckDBの初期化
async function initDuckDB() {
const JSDELIVR_BUNDLES = {
mvp: {
mainModule: 'https://cdn.jsdelivr.net/npm/@duckdb/duckdb-wasm/dist/duckdb-mvp.wasm',
mainWorker: 'https://cdn.jsdelivr.net/npm/@duckdb/duckdb-wasm/dist/duckdb-browser-mvp.worker.js',
},
eh: {
mainModule: 'https://cdn.jsdelivr.net/npm/@duckdb/duckdb-wasm/dist/duckdb-eh.wasm',
mainWorker: 'https://cdn.jsdelivr.net/npm/@duckdb/duckdb-wasm/dist/duckdb-browser-eh.worker.js',
},
};
const bundle = await duckdb.selectBundle(JSDELIVR_BUNDLES);
const worker = new Worker(bundle.mainWorker);
const logger = new duckdb.ConsoleLogger();
return new duckdb.AsyncDuckDB(logger, worker);
}
ライセンス情報の表示
各論文のライセンス情報を取得して表示する機能を実装し、ユーザーが論文の利用条件を確認しやすくなりました。
// ライセンス情報の取得
async function fetchLicenseInfo(arxivId) {
// ライセンス情報を取得するLambda関数のURL
const lambdaUrl = `https://osn5tu5yh4jm52xsickxysoyq0pymqn.lambda-url.ap-northeast-1.on.aws/?id=${cleanId}`;
// ライセンスの種類に応じた表示スタイルの設定
if (data.license_found) {
let licenseText = data.license;
let licenseColor = "#888";
let licenseIcon = "";
// ライセンスタイプに基づいて色とアイコンを設定
if (data.type === 'cc-by') {
licenseColor = "#4CAF50"; // Green
licenseIcon = '<img src="https://mirrors.creativecommons.org/presskit/buttons/88x31/svg/by.svg" width="60" height="20" alt="CC BY" style="vertical-align: middle;" />';
} else if (data.type === 'cc-by-sa') {
licenseColor = "#8BC34A"; // Light green
licenseIcon = '<img src="https://mirrors.creativecommons.org/presskit/buttons/88x31/svg/by-sa.svg" width="60" height="20" alt="CC BY-SA" style="vertical-align: middle;" />';
}
// ... 他のライセンスタイプも同様に処理
}
}
モバイル対応の強化
レスポンシブデザインを改善し、モバイルデバイスでの使いやすさを向上させました。特にiOS向けの最適化を行い、ホーム画面へのインストールガイドを追加しました。
<div id="ios-install-guide" class="ios-install-guide">
<h3>Install as App on iOS</h3>
<ol>
<li>Tap the share icon <i class="fas fa-share-square"></i> at the bottom of your screen.</li>
<li>Scroll down and tap "Add to Home Screen".</li>
<li>Tap "Add" in the top-right corner.</li>
<li>Open the app from your home screen to enable notifications.</li>
</ol>
</div>
今後の展望
現在、以下の機能の開発を検討しています:
- 論文の自動推薦機能
- ユーザープロフィールとカスタマイズ設定
- 論文間の関連性ネットワーク表示
- より高度なフィルタリングオプション
- オープンAPIの提供
まとめ
q-finderは量的金融論文の発見と管理をより効率的に行えるよう、様々な新機能を追加しました。特にマイページ、ランキング、検索機能の強化により、ユーザーは自分の興味に合った論文を素早く見つけることができます。またPWA対応により、モバイルデバイスでも快適に利用できるようになりました。
今後もユーザーフィードバックを取り入れながら、機能の強化を続けていく予定です。q-finderをぜひご利用いただき、ご意見・ご感想をお聞かせください。