東証からは毎日各銘柄の8本値が公表されているが、pdfで記載されているのが困ったところ。しかも時期によって記載内容が異なっている。例えば、2024-07以降は銘柄毎に売買株数、売買代金が記載された日報が公表されている。しかし、2020-01 ~ 2024-07では月報が公表され、そこには売買株数、売買代金の記載がない。
2019-12以前では(2011-01まで)日報がZipアーカイブされて公表されそこにはそこには売買株数、売買代金の記載がある。 もっとも古いデータは1949-05-16であるが非常に読み難いtif画像で入手できる。当時の銘柄数は400位である。銘柄コードは無い。
-
Ruby
require 'logger' log_file = File.open('stq2csvExe.log', 'a') $logger = Logger.new(log_file) $logger.formatter = proc do |severity, datetime, progname, msg| "#{datetime}: #{msg}\n" end require 'pdf-reader' require 'open-uri' require 'sqlite3' # puts 'required pdf filename' if ARGV.count.zero? # reader = PDF::Reader.new ARGV[0] def makeFileObj date urlStr = "https://www.jpx.co.jp/markets/statistics-equities/" + "daily/mklp77000000d1sb-att/stq_#{date}.pdf" file = nil retry_count = 0 begin file = URI.open(urlStr) rescue StandardError => e if e.is_a?(OpenURI::HTTPError) && e.io.status[0] == '404' $logger.error "File not found at #{urlStr}. Not retrying." # raise e end retry_count += 1 if retry_count < 3 $logger.warn "URI.open failed, retrying... (#{retry_count}/3). Error: #{e.message}" sleep(1) retry else $logger.error "Failed to open URL after 3 attempts." end end return file end date = '20240731' file = makeFileObj(date) exit if file.nil? reader = PDF::Reader.new file all_lines = [] reader.pages.each do |page| all_lines.concat(page.text.split("\n")) end lines = [] all_lines.each do |line| break if line.match(/立 会 市 場.* 当 日 決 済 取 引/) lines << line end lines.select! { |line| line.match(/^[1-9][A-Z0-9]{3}/) } lines.map! { |e| e.gsub /^([1-9][A-Z0-9]{3})[ ]+[A-Z#]/, '\1' } lines.map! { |e| e.gsub /[ ][ ]*/, '|' } 2.times do lines.map! do |e| line = e.split '|' if line[2] && line[3] && line[2].match?(/[^a-zA-Z0-9,-\.]/) && line[3].match?(/[^a-zA-Z0-9,-\.]/) line[2] = "#{line[2]} #{line[3]}" line.delete_at(3) end line.join '|' # line end end db = SQLite3::Database.new 'stock8.db' lines.each do |line| values = line.split '|' code = values[0] db.execute <<-SQL CREATE TABLE IF NOT EXISTS '#{code}' ( date TEXT, unit TEXT, company TEXT, openam TEXT, higham TEXT, lowam TEXT, closeam TEXT, openpm TEXT, highpm TEXT, lowpm TEXT, closepm TEXT, finalSpecialQuote TEXT, NetChange TEXT, vwap TEXT, volume TEXT, value TEXT ); SQL db.execute("INSERT INTO '#{code}' VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", [date] + values[1..-1]) end db.close __END__ 銘柄コードが1305 D(配当落ち)である場合を考慮。銘柄名にスペースが含む場合を考慮。Openが−である場合にも対応。確認は、Table Tool.appで行った。 R-XXX: REIT 国内投資証券 P-XXX: Pro Market G-XXX: Growth Market
-
stock8.db
sqlite> select * from '1301'; date|unit|company|openam|higham|lowam|closeam|openpm|highpm|lowpm|closepm|finalSpecialQuote|NetChange|vwap|volume|value 20240731|100|極洋|3,980.00|4,020.00|3,955.00|4,020.00|4,010.00|4,055.00|4,010.00|4,055.00|-|60.00|4,021.9018|16.3|65,557
-
Gemini CLIへ与えたPrompt
改良前はstdout経由にCSVへ保存する目的で、文字列格納のlines配列を書き出していた。それをデータベースへ保存するコードをGemini CLIで自動生成してみた。
puts linesの部分を次のように改良して下さい 1. sqlite3のstock8.dbに値を保存 2. 文字列linesは銘柄情報が格納された配列の配列です。銘柄情報が格納された配列には次の値が格納されています。すべて文字列型です。 [code, unit, company, openam, higham, lowam, closeam, openpm, highpm, lowpm, closepm, finalSpecialQuote, NetChange, vwap, volume, value] 3. 文字列codeのテーブルを作成して下さい。 4. テーブルには次の情報が格納出来るようにして下さい [date, unit, company, openam, higham, lowam, closeam, openpm, highpm, lowpm, closepm, finalSpecialQuote, NetChange, vwap, volume, value] 5. テーブル作成後、銘柄情報が格納された配列の内容をテーブルへ格納して下さい
-