Poolでブロック報酬が当たった場合1.75 XCH分も記録されていました。それを削除するupdateはこちらです。取得時収入円表示スクリプト update
お約束していたものができました。思ったより難航して、遅くなりました。みずほ銀行の円ドルレートは営業日分しかないので、足りないところは補間(前日値)する必要があったり、所持金総額が19mojoずれていたりいろいろありました。とりあえず公開しますので、おつきあい頂ける方はバグだし、ご意見頂けますでしょうか・・・
まず悲報です。このスクリプトの結果によって、現在のXCH初期額が5万7千円なのに対して、確定申告時には12万円の収入を申告しなければなりません。思ったよりも差がありました。最近のXCH価格下落も効いてます。
19mojoずれているのはうちだけだろうか・・・。おつきあい頂ける方は是非、ずれているかどうか教えてください。ここでずれるよ、などわかると助かります。
さて、プログラムの説明に行きましょう。以前紹介した WalletからCSV取り出す方法と、CoinGeckoからXCHプライスリストを取得する方法と組み合わせて使います。
こんなバッチファイルをつくって起動しましょう。
1 2 3 4 5 6 7 |
c:\sqlite3\sqlite3 -readonly C:\Users\<ユーザー名>\.chia\mainnet\wallet\db\blockchain_wallet_v1_mainnet_XXXXXXXXXX.sqlite ".mode csv" ".output wallet.csv" "SELECT sent, to_puzzle_hash , datetime(created_at_time, 'unixepoch', 'localtime'), hex(amount) FROM transaction_record;" rem Anaconda Virtual Environment activate call C:\Users\<ユーザー名>\anaconda3\Scripts\activate.bat call activate p38 python C:\python\to-jpy.py |
そしてPythonスクリプト本体はこちら。思ったよりも大きくなりました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# import import numpy as np import pandas as pd import datetime as dt from urllib import request import urllib.error import urllib.request from bs4 import BeautifulSoup # 必要なら $ conda install beautifulsoup4 # coingecko の XCH price table を表示。start, end の日時を指定できる start_date='2020-05-04' end_date ='2021-09-28' url = f'https://www.coingecko.com/en/coins/chia/historical_data/usd?end_date={end_date}&start_date={start_date}#panel' # ブラウザの真似しないと HTTP Error 403: Forbidden にされる。 headers = { "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:47.0) Gecko/20100101 Firefox/47.0" } # 追加 request = urllib.request.Request(url, headers=headers) # headers を追加 try: with urllib.request.urlopen(request) as web_file: urldata = web_file.read() except urllib.error.URLError as e: print(e) # urldata の欲しいところを抽出 soup = BeautifulSoup(urldata, 'html.parser') body = soup.select('.table') # テキスト抽出して、'$'を削除して、リスト化 l = body[0].get_text().replace('$', '').split() # column名を削除 del l[:6] # numpy 使って、2次元化 n2 = np.array(l).reshape(-1,5) # pandas DataFrameに変換 xdf = pd.DataFrame(n2, columns=['Date','MarketCap','Volume','Open','Close']) # 【暫定】MarketCapで0.000000000000 は 0 に置き換える xdf.loc[xdf['MarketCap']=='0.000000000000', 'MarketCap'] = '0' # CSV fileとして保存 xdf.to_csv('xch-price.csv', index=False) # 一度 csv で保存して、thousands=',' をつけて read_csv すると、いい感じに文字列数値変換してくれる。便利! xdf = pd.read_csv('xch-price.csv', thousands=',') # 【暫定】最新日CloseがNaN(オリジナルでは'N/A')の場合にはOpenの値を入れておく xdf.loc[np.isnan(xdf['Close']), 'Close'] = xdf['Open'] # いらない列を削除 xdf.drop(['MarketCap', 'Volume', 'Open'], axis=1, inplace=True) # 辞書を作る。mapで一度に適用できて便利 keys = xdf['Date'] values = xdf['Close'] date2xch = dict(zip(keys, values)) mizuho_url = 'https://www.mizuhobank.co.jp/market/quote.csv' # ブラウザの真似しないと HTTP Error 403: Forbidden にされる。 headers = { "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:47.0) Gecko/20100101 Firefox/47.0" } # 追加 request = urllib.request.Request(mizuho_url, headers=headers) # headers を追加 try: with urllib.request.urlopen(request) as web_file: urldata = web_file.read() except urllib.error.URLError as e: print(e) # 一度CSVファイルとして書き込み with open('mizuho_hist.csv', 'wb') as f: f.write(urldata) # シフトJISで読み込み直し。thousands=','はたぶんいらない mdf = pd.read_csv('mizuho_hist.csv', thousands=',', encoding="SHIFT-JIS") # 列名を整数で振り直し sh = mdf.shape mdf.columns = range(sh[1]) # 1列目(日付)、2列目(米ドル)のみ抽出 mdf = mdf.loc[:,[0,1]] # 最初の2行を削除 mdf.drop([0, 1], axis=0, inplace=True) # 列名ふりなおし mdf.columns = ['Date', 'JPY/USD'] # 一度 datetime 型にして mdf['Date'] = pd.to_datetime(mdf['Date']) # 日付datetime型をつかいやすい文字列に mdf['Date'] = mdf['Date'].dt.strftime('%Y-%m-%d') # JPY/USD の数値が文字列なのでfloatに変換 mdf['JPY/USD'] = mdf['JPY/USD'].astype(float) #################################################### # 日本円 Wallet 表作成 #################################################### # 16進数文字列を10進数に変換する関数, map関数でDataFrameに適用できる def func(value): return int(value, 16) # CSV ファイルを読み込み df = pd.read_csv('wallet.csv', names=['入出', '宛先', '日時(str)', '金額(16進)']) # 日付文字列を datetime型に変換。pandasのpd.to_datetimeが使える df['日時']=pd.to_datetime(df['日時(str)']) df['月日(str)'] = df['日時'].dt.strftime('%Y-%m-%d') # 16進数文字列を整数にして、入出が0のときは正の数(入金)、1のときは負の数(出金)とする df['金額(mojo)']=df['金額(16進)'].map(func) * ((-1)**df['入出']) df['累積金額(mojo)']=df['金額(mojo)'].cumsum() # 使っている宛先名と最初数文字のaddress16進数文字列(Pool名やPlot NFT名)を辞書型で登録してください add2name = { 'PoolChia' : '238f', 'HDDMining' : '938e', 'ブロック報酬' : '3cab', 'サブアカ' : '1baa'} # 戦闘数文字で引っかけているので、残念ながらmapは使えない for n in add2name.keys(): df.loc[df['宛先'].str.startswith(add2name[n]), '取引相手'] = n # 余計な列を削ってWallet表ののひな形とする walj = df.drop(['入出', '宛先', '日時(str)', '金額(16進)'], axis=1) # ★★★ XCH価格を埋め込み walj['XCH価格'] = walj['月日(str)'].map(date2xch) ##################### # みずほデータには日本の休日など抜けている日がある。 # wallet_dfから足りない日付を加えて、為替値は前後値から補間 ##################### # みずほ銀行の古すぎるデータは除外 ndf = mdf[mdf['Date'] >= '2021-04-30'] # Dateからそれぞれの就業をつくる n_set = set(ndf['Date']) w_set = set(walj['月日(str)']) # 集合の引き算で xdf に存在しない日にちを見つける sub = w_set - n_set # ndf のindexをDateにして、存在しないDateで行を作れるようにする ndf = ndf.set_index('Date') # 存在しないDateで新しい行を作る for d in sub: ndf.loc[d] = np.nan # index でソート ndf = ndf.sort_index() # NaN値のあるところを前日の値で補間 ndf = ndf.fillna(method='ffill') ndf = ndf.reset_index() # 変換辞書をつくる。mapで使う。 keys = ndf['Date'] values = ndf['JPY/USD'] date2jpy = dict(zip(keys, values)) # ★★★ 円/ドル相場埋め込み walj['JPY/USD'] = walj['月日(str)'].map(date2jpy) icchou = 1000000000000 # 一兆 1兆mojo = 1 XCH # 日本円取得価格計算 walj['収入(円)'] = walj['金額(mojo)'] * walj['XCH価格'] * walj['JPY/USD'] / icchou walj['収入(円)str'] = walj['収入(円)'].apply(lambda x: '{:.2f}'.format(x)) walj['税法上収入(円)'] = walj['収入(円)'].cumsum() walj['所持金(円)'] = walj['累積金額(mojo)'] * walj['XCH価格'] * walj['JPY/USD'] / icchou walj.to_csv('wal-jpy.csv', index=False) |
円ドル相場ヒストリカルデータはみずほ銀行さんが公開してくれています。
できたてなので、バグがあるかもしれませんが、興味のある方は是非使ってみて、ご意見ください。