メルカリの暗号資産(ビットコインBTC、イーサリアムETH、XRP)の月間取引報告書CSVファイルから 確定申告のために年間の損益計算をするためのRubyスクリプトmercari.rbと それをCrystal言語に移植したmercari.cr
ライセンスは GPLv3 で、完全無保証です。税務署に怒られてもしりません。
参考文献: https://help.jp.mercari.com/guide/articles/1513/ メルカル ビットコイン取引 取引報告書・損益計算方法
Author: Takeshi Nishimatsu
目的 (Purpose): メルカリで暗号資産取引をしている人の確定申告 (Japanese tax return)
使い方 (Usage): LANG=ja_JP.UTF-8 ruby mercari.rb report_2024?.csv report_20241?.csv
計算書: 実行すると標準出力される年中購入または年中売却の数量と金額を国税庁の総平均法用002.xlsx計算書にコピペ
表計算: CSVファイルも同時に出力されるのでエクセルなどで開くと表の最下行でも年中の数量と金額がわかる
出力CSVファイル: btc_buy.csv, btc_sel.csv, eth_buy.csv, eth_sel.csv, xrp_buy.csv, xrp_sel.csv
実行例:
$ LANG=ja_JP.UTF-8 ruby mercari.rb report_2024?.csv report_20241?.csv
btc_buy.csv has 7 transactions. Total: 0.000411220 JPY: 4237
btc_sel.csv has 5 transactions. Total: 0.000323540 JPY: 4680
eth_buy.csv has 2 transactions. Total: 0.005641040 JPY: 2132
eth_sel.csv has 2 transactions. Total: 0.000695680 JPY: 500
xrp_buy.csv has 0 transactions. Total: 0.000000000 JPY: 0
xrp_sel.csv has 0 transactions. Total: 0.000000000 JPY: 0
目的 (Purpose): ちょっとCrystalを書いてみた。後述の通りどのくらい高速化するか検証した。
使い方 (Usage): crystal build mercari.cr --release && ./mercari report_2024?.csv report_20241?.csv
比較 (Compare): diff -ub mercari.rb mercari.cr
計算書: 実行すると標準出力される年中購入または年中売却の数量と金額を国税庁の総平均法用002.xlsx計算書にコピペ
表計算: CSVファイルも同時に出力されるのでエクセルなどで開くと表の最下行でも年中の数量と金額がわかる
出力CSVファイル: btc_buy.csv, btc_sel.csv, eth_buy.csv, eth_sel.csv, xrp_buy.csv, xrp_sel.csv
実行例:
$ crystal build mercari.cr --release && ./mercari report_2024?.csv report_20241?.csv
btc_buy.csv has 7 transactions. Total: 0.000411220 JPY: 4237
btc_sel.csv has 5 transactions. Total: 0.000323540 JPY: 4680
eth_buy.csv has 2 transactions. Total: 0.005641040 JPY: 2132
eth_sel.csv has 2 transactions. Total: 0.000695680 JPY: 500
xrp_buy.csv has 0 transactions. Total: 0.000000000 JPY: 0
xrp_sel.csv has 0 transactions. Total: 0.000000000 JPY: 0
感想を忘れないうちに箇条書き。
- Crystal 1.17.1 (2025-07-22) を使った。
- macOSなら
brew install crystalだけで使えるようになった。 - CrystalはOCamlなみに型にうるさいRuby。
crystal build mercari.crとコンパイルするとmercariができる。 コンパイルオプション--releaseを付けると最適化された高速なバイナリができる。- GrokとかAIにRubyスクリプトをコピーアンドペーストしてCrystalに書き直すよう指示すると、まあまあよいかんじに直してくれる。
- AIが関数やメソッドの引数の型まで推定してくれる。
- Fortranのクセで
if (a==b) thenと書きがちだが、Rubyではthenを省略できる。Crystalだとthenはエラー。 - RubyでもCrystalでも
if a==bとカッコはいらない。 andとorはCrystalではエラーになるので&&と||を使っておく。"".to_fはRubyなら0.0、Crystalだどエラー。- Rubyの
ARGF.each{|line| }は改行までlineに格納される。 - Crystalには今のところ
ARGFがない。 - Crystalでは
ARGV.each do |filename|;File.each_line(filename) do |line|とする。 - CrystalではArray, Hashなどに複数種類の型を格納できない。
- 空のHashはRubyなら
{}だけでよいが、CrystalだとHash(String,OutputCSV).newなどと書かなくてはいけない。 - Rubyの
open(@filename, "w")はCrystalではFile.open(@filename, "w")に直す。 - 参考になりそうな文章
- 日本語のドキュメントが充実してる https://ja.crystal-lang.org/reference/
- Crystalでコマンドラインツールを作って気づいた12のこと https://qiita.com/kojix2/items/c305d46aafd2b51a153c
- Crystalの小さな本 https://qiita.com/tadnakam/items/b1c2e32e86135db63c30
- 続・Crystalの小さな本 https://qiita.com/tadnakam/items/c88c4fedc4dd3479331a
640 MBの大きなUTF-8な日本語を含むcsvファイルを用意し、RubyとCrystalのベンチマークを行う。
$ git clone https://gist.github.com/22a4a9525d423208c7f784ce507d0bc5.git mercari
$ cd mercari
$ for i in {1..100000}; do cat report_2024?.csv report_20241?.csv; done > large.csv
$ ls -lh large.csv
-rw-r--r-- 1 t-nissie staff 639M 12 7 08:45 large.csv
$ export LANG=ja_JP.UTF-8
$ ruby --version
ruby 3.4.4 (2025-05-14 revision a38531fd3f) +PRISM [arm64-darwin24]
$ time ruby mercari.rb report_2024?.csv report_20241?.csv large.csv
$ time ruby --jit mercari.rb report_2024?.csv report_20241?.csv large.csv
$ time ruby --yjit mercari.rb report_2024?.csv report_20241?.csv large.csv
$ time ./mercari-fastest-csv.rb report_2024?.csv report_20241?.csv large.csv
$ crystal --version
Crystal 1.17.1 (2025-07-22)
$ crystal build mercari.cr && time ./mercari report_2024?.csv report_20241?.csv large.csv
$ crystal build mercari.cr --release && time ./mercari report_2024?.csv report_20241?.csv large.csv
表:ベンチマークの結果
| コマンド | 実行速度(秒) | コメント |
|---|---|---|
| ruby | 16.957 | |
| ruby --jit | 16.102 | |
| ruby --yjit | 16.056 | |
| mercari-fastest-csv.rb | NG (7.46) | UTF-8日本語に対応していないようで動かなかった |
| mercari-nesquikcsv.rb | 11.117 | NesqickCSVはUTF-8に対応している |
| crystal build | 17.112 | |
| crystal build --release | 3.224 | コンパイルオプション--releaseを忘れてはいけない |
大きなCSVファイルの処理を行う場合、 Crystalによって、Rubyスクリプトを少し変更するだけで、5倍以上の高速化が可能なことがわかった。
今回の用途では--jit, --yjitとも高速化できなかった。
FastestCSVはUTF-8日本語に対応していない。 NesqickCSV https://github.com/jmartty/nesquikcsv はUTF-8に対応している。
btc_buy.csvなどのCSVファイルでの出力をあきらめればさらに高速化できそう。
Use CSV library instead of split(','). But, note that:
- Use csv gem version 3.3.3 or higher. https://rubygems.org/gems/csv
- Old CSV.filter can't read more than two files from ARGF. ruby/csv#328
- We can't remove any rows by CSV.filter. ruby/csv#293
2025年の月間取引報告書CSVファイルでテスト