diff --git a/jquants-api-quick-start-v2.ipynb b/jquants-api-quick-start-v2.ipynb new file mode 100644 index 0000000..6c6a223 --- /dev/null +++ b/jquants-api-quick-start-v2.ipynb @@ -0,0 +1,1489 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "view-in-github", + "colab_type": "text" + }, + "source": [ + "\"Open" + ] + }, + { + "cell_type": "code", + "source": [], + "metadata": { + "id": "qdQBBcZtbHXv" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "pdlborFttnt2" + }, + "source": [ + "# J-Quants API V2 Quick Startガイド" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "cellView": "form", + "id": "CpwnfBFRGVfW" + }, + "outputs": [], + "source": [ + "#@title 初期設定&各種import\n", + "#@markdown ←にある▶ボタンを押すとGoogle Colabでコードを実行することができます。\n", + "\n", + "#@markdown まずはこちらのコードを実行し、J-Quants APIを利用するため必要なパッケージをimportしましょう。\n", + "\n", + "import json\n", + "import sys\n", + "import requests\n", + "\n", + "from IPython.display import display\n", + "import pandas as pd\n", + "\n", + "pd.set_option(\"display.max_columns\", None)\n", + "\n", + "API_URL = \"https://api.jquants.com/v2\"" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "aMdAC0xHGONW" + }, + "source": [ + "## Step1:API利用開始までの流れ ※初回のみ実施" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Hp4c7WfZwlRf" + }, + "source": [ + "J-Quants APIのご利用を検討いただき、ありがとうございます。\n", + "\n", + "**J-Quants APIをご利用いただくには、以下の2つを事前に行っていただく必要がございます。**\n", + " 1. [J-Quants Webサイト](https://jpx-jquants.com/)への登録\n", + " 2. J-Quants API利用のためのプラン(Free, Light, Standard, Premium)選択\n", + "\n", + "まだ、ご登録もしくはプラン選択がお済みでない方は、まず上記の2項目を行っていただきますようお願いいたします。 \n", + "より具体的な手順は[こちら](https://jpx-jquants.com/ja/spec/quickstart)をご参照ください。" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "m6YTkXxL1QKp" + }, + "source": [ + "## Step2:APIキー取得\n", + "\n", + "V2ではAPIキー方式による認証を採用しています。\n", + "\n", + "APIキーはJ-Quants Webサイトのダッシュボードページから取得できます。\n", + "\n", + "1. [J-Quants Webサイト](https://jpx-jquants.com/)にログイン\n", + "2. ダッシュボードページにアクセス\n", + "3. APIキーを取得(APIキーに有効期限はありません)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "cellView": "form", + "id": "2x9O_8mOtyRU" + }, + "outputs": [], + "source": [ + "#@title **APIキーを設定**\n", + "#@markdown J-Quants WebサイトのダッシュボードにてAPIキーを取得し、以下に貼り付けてください。\n", + "\n", + "api_key = \"\"#@param {type: \"string\"}\n", + "\n", + "if api_key:\n", + " headers = {\"x-api-key\": api_key}\n", + " print(\"APIキーが設定されました。J-Quants APIを利用する準備が完了しました。\")\n", + "else:\n", + " print(\"APIキーを入力してください。\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "-Eurw3gqIAi3" + }, + "source": [ + "## Step3:取得したAPIキーを用いて各APIをご利用ください。" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "IYgHOfBGh_w8" + }, + "source": [ + "### Freeプラン以上のプランで利用できるAPI\n", + "- 上場銘柄一覧(/equities/master)\n", + "- 株価四本値*(/equities/bars/daily)\n", + "- 財務情報(/fins/summary)\n", + "- 決算発表予定日(/equities/earnings-calendar)\n", + "- 取引カレンダー(/markets/calendar)\n", + "\n", + "\\* プレミアムプランのユーザのみ、前後場の四本値及び取引高・取引代金の情報が取得可能\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "cellView": "form", + "id": "epk4nH_4q611" + }, + "outputs": [], + "source": [ + "#@title 上場銘柄一覧(/equities/master)\n", + "\n", + "#@markdown - 過去時点での銘柄情報、当日の銘柄情報および翌営業日時点の銘柄情報が取得可能です。\n", + "#@markdown - データの取得では、銘柄コード(code)または日付(date)の指定が可能です。\n", + "\n", + "#@markdown (データ更新時刻)\n", + "#@markdown - 毎営業日の17:30頃、翌営業日の8:00頃\n", + "\n", + "code = \"\"#@param {type:\"string\"}\n", + "date = \"\"#@param {type:\"string\"}\n", + "\n", + "params = {}\n", + "if code != \"\":\n", + " params[\"code\"] = code\n", + "if date != \"\":\n", + " params[\"date\"] = date\n", + "\n", + "res = requests.get(f\"{API_URL}/equities/master\", params=params, headers=headers)\n", + "\n", + "if res.status_code == 200:\n", + " d = res.json()\n", + " data = d[\"data\"]\n", + " while \"pagination_key\" in d:\n", + " params[\"pagination_key\"] = d[\"pagination_key\"]\n", + " res = requests.get(f\"{API_URL}/equities/master\", params=params, headers=headers)\n", + " d = res.json()\n", + " data += d[\"data\"]\n", + " df = pd.DataFrame(data)\n", + " display(df)\n", + "else:\n", + " print(res.json())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "cellView": "form", + "id": "Oo1qg0OOrC6L" + }, + "outputs": [], + "source": [ + "#@title 株価四本値(/equities/bars/daily)\n", + "\n", + "#@markdown - 株価は分割・併合を考慮した調整済み株価(小数点第2位四捨五入)と調整前の株価を取得することができます。\n", + "#@markdown - データの取得では、銘柄コード(code)または日付(date)の指定が必須となります。\n", + "\n", + "#@markdown (データ更新時刻)\n", + "#@markdown - 毎営業日の17:00頃\n", + "\n", + "#@markdown - Premiumプランの方には、日通しに加え、前場(Morning)及び後場(Afternoon)の四本値及び取引高(調整前・後両方)・取引代金が取得可能です。\n", + "\n", + "\n", + "code = \"\"#@param {type:\"string\"}\n", + "date = \"\"#@param {type:\"string\"}\n", + "from_ = \"\" #@param {type:\"string\"}\n", + "to = \"\" #@param {type:\"string\"}\n", + "\n", + "params = {}\n", + "if code != \"\":\n", + " params[\"code\"] = code\n", + "if date != \"\":\n", + " params[\"date\"] = date\n", + "if from_ != \"\":\n", + " params[\"from\"] = from_\n", + "if to != \"\":\n", + " params[\"to\"] = to\n", + "\n", + "res = requests.get(f\"{API_URL}/equities/bars/daily\", params=params, headers=headers)\n", + "\n", + "if res.status_code == 200:\n", + " d = res.json()\n", + " data = d[\"data\"]\n", + " while \"pagination_key\" in d:\n", + " params[\"pagination_key\"] = d[\"pagination_key\"]\n", + " res = requests.get(f\"{API_URL}/equities/bars/daily\", params=params, headers=headers)\n", + " d = res.json()\n", + " data += d[\"data\"]\n", + " df = pd.DataFrame(data)\n", + " display(df)\n", + "else:\n", + " print(res.json())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "cellView": "form", + "id": "HqcpHjObrPqA" + }, + "outputs": [], + "source": [ + "#@title 財務情報(/fins/summary)\n", + "\n", + "#@markdown - 財務情報APIでは、上場企業がTDnetへ提出する決算短信Summary等を基に作成された、四半期毎の財務情報を取得することができます。\n", + "#@markdown - データの取得では、銘柄コード(code)または開示日(date)の指定が必須です。\n", + "\n", + "#@markdown (データ更新時刻)\n", + "#@markdown - 速報18:00頃、確報24:30頃\n", + "\n", + "\n", + "code = \"\"#@param {type:\"string\"}\n", + "date = \"\"#@param {type:\"string\"}\n", + "\n", + "params = {}\n", + "if code != \"\":\n", + " params[\"code\"] = code\n", + "if date != \"\":\n", + " params[\"date\"] = date\n", + "\n", + "res = requests.get(f\"{API_URL}/fins/summary\", params=params, headers=headers)\n", + "\n", + "if res.status_code == 200:\n", + " d = res.json()\n", + " data = d[\"data\"]\n", + " while \"pagination_key\" in d:\n", + " params[\"pagination_key\"] = d[\"pagination_key\"]\n", + " res = requests.get(f\"{API_URL}/fins/summary\", params=params, headers=headers)\n", + " d = res.json()\n", + " data += d[\"data\"]\n", + " df = pd.DataFrame(data)\n", + " display(df)\n", + "else:\n", + " print(res.json())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "cellView": "form", + "id": "ZSjHBYg6rWTK" + }, + "outputs": [], + "source": [ + "#@title 決算発表予定日(/equities/earnings-calendar)\n", + "\n", + "#@markdown (データ更新時刻)\n", + "#@markdown - 不定期(更新がある日は)19:00頃\n", + "\n", + "#@markdown - [当該ページ](https://www.jpx.co.jp/listing/event-schedules/financial-announcement/index.html)で、3月期・9月期決算会社分に更新があった場合のみ19時ごろに更新されます。\n", + "\n", + "params = {}\n", + "\n", + "res = requests.get(f\"{API_URL}/equities/earnings-calendar\", params=params, headers=headers)\n", + "\n", + "if res.status_code == 200:\n", + " d = res.json()\n", + " data = d[\"data\"]\n", + " while \"pagination_key\" in d:\n", + " params[\"pagination_key\"] = d[\"pagination_key\"]\n", + " res = requests.get(f\"{API_URL}/equities/earnings-calendar\", params=params, headers=headers)\n", + " d = res.json()\n", + " data += d[\"data\"]\n", + " df = pd.DataFrame(data)\n", + " display(df)\n", + "else:\n", + " print(res.json())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "cellView": "form", + "id": "4xAYSViFw2ND" + }, + "outputs": [], + "source": [ + "#@title 取引カレンダー(/markets/calendar)\n", + "\n", + "#@markdown - 東証およびOSEにおける営業日、休業日、ならびにOSEにおける祝日取引の有無の情報を取得できます。\n", + "#@markdown - データの取得では、休日区分(hol_div)または日付(from/to)の指定が可能です。\n", + "\n", + "#@markdown (データ更新日)\n", + "#@markdown - 不定期(原則として、毎年2月頃をめどに翌年1年間の営業日および祝日取引実施日(予定)を更新します。)\n", + "\n", + "\n", + "hol_div = \"\"#@param [\"0\", \"1\", \"2\", \"3\"]{allow-input:true}\n", + "from_ = \"\" #@param {type:\"string\"}\n", + "to = \"\" #@param {type:\"string\"}\n", + "\n", + "params = {}\n", + "if hol_div != \"\":\n", + " params[\"hol_div\"] = hol_div\n", + "if from_ != \"\":\n", + " params[\"from\"] = from_\n", + "if to != \"\":\n", + " params[\"to\"] = to\n", + "\n", + "res = requests.get(f\"{API_URL}/markets/calendar\", params=params, headers=headers)\n", + "\n", + "if res.status_code == 200:\n", + " d = res.json()\n", + " data = d[\"data\"]\n", + " while \"pagination_key\" in d:\n", + " params[\"pagination_key\"] = d[\"pagination_key\"]\n", + " res = requests.get(f\"{API_URL}/markets/calendar\", params=params, headers=headers)\n", + " d = res.json()\n", + " data += d[\"data\"]\n", + " df = pd.DataFrame(data)\n", + " display(df)\n", + "else:\n", + " print(res.json())" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "QtsUDLLnnsaA" + }, + "source": [ + "### Lightプラン以上のプランで利用できるAPI\n", + "- 投資部門別情報(/equities/investor-types)\n", + "- TOPIX四本値(/indices/bars/daily/topix)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "cellView": "form", + "id": "3JSzR-JDrtgq" + }, + "outputs": [], + "source": [ + "#@title 投資部門別(株式)データ(/equities/investor-types)\n", + "\n", + "#@markdown - 投資部門別売買状況(金額)のデータを取得することができます。\n", + "#@markdown - 投資部門別売買状況は、個人・外国人・金融機関など、投資家ごとの売買動向をまとめた情報です。\n", + "#@markdown - 基本的には[こちら](https://www.jpx.co.jp/markets/statistics-equities/investor-type/index.html)のページで掲載しているものと同等のものになります。\n", + "#@markdown - データの取得では、セクション(section)または日付(from/to)の指定が可能です。\n", + "\n", + "#@markdown (データ更新時刻)\n", + "#@markdown - 原則、毎週第4営業日18:00頃\n", + "\n", + "\n", + "section = \"\"#@param [\"TSE1st\", \"TSE2nd\", \"TSEMothers\", \"TSEJASDAQ\", \"TSEPrime\", \"TSEStandard\", \"TSEGrowth\", \"TokyoNagoya\"] {allow-input: true}\n", + "from_ = \"\" #@param {type:\"string\"}\n", + "to = \"\" #@param {type:\"string\"}\n", + "\n", + "params = {}\n", + "if section != \"\":\n", + " params[\"section\"] = section\n", + "if from_ != \"\":\n", + " params[\"from\"] = from_\n", + "if to != \"\":\n", + " params[\"to\"] = to\n", + "\n", + "res = requests.get(f\"{API_URL}/equities/investor-types\", params=params, headers=headers)\n", + "\n", + "if res.status_code == 200:\n", + " d = res.json()\n", + " data = d[\"data\"]\n", + " while \"pagination_key\" in d:\n", + " params[\"pagination_key\"] = d[\"pagination_key\"]\n", + " res = requests.get(f\"{API_URL}/equities/investor-types\", params=params, headers=headers)\n", + " d = res.json()\n", + " data += d[\"data\"]\n", + " df = pd.DataFrame(data)\n", + " display(df)\n", + "else:\n", + " print(res.json())\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "cellView": "form", + "id": "ssdsMVgprnVr" + }, + "outputs": [], + "source": [ + "#@title TOPIX四本値(/indices/bars/daily/topix)\n", + "\n", + "#@markdown - 日次のTOPIX指数の四本値について取得することができます。\n", + "#@markdown - 日付(from/to)の指定が可能です\n", + "\n", + "#@markdown (データ更新時刻)\n", + "#@markdown - 毎営業日の16:30頃\n", + "\n", + "\n", + "date_from = \"\"#@param {type:\"string\"}\n", + "date_to = \"\"#@param {type:\"string\"}\n", + "\n", + "params = {}\n", + "\n", + "if date_from != \"\":\n", + " params[\"from\"] = date_from\n", + "if date_to != \"\":\n", + " params[\"to\"] = date_to\n", + "\n", + "res = requests.get(f\"{API_URL}/indices/bars/daily/topix\", params=params, headers=headers)\n", + "\n", + "if res.status_code == 200:\n", + " d = res.json()\n", + " data = d[\"data\"]\n", + " while \"pagination_key\" in d:\n", + " params[\"pagination_key\"] = d[\"pagination_key\"]\n", + " res = requests.get(f\"{API_URL}/indices/bars/daily/topix\", params=params, headers=headers)\n", + " d = res.json()\n", + " data += d[\"data\"]\n", + " df = pd.DataFrame(data)\n", + " display(df)\n", + "else:\n", + " print(res.json())\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "cYPQBHkinwgd" + }, + "source": [ + "### Standard以上のプランで利用できるAPI\n", + "- 指数四本値(/indices/bars/daily)\n", + "- 日経225オプション四本値(/derivatives/bars/daily/options/225)\n", + "- 信用取引週末残高(/markets/margin-interest)\n", + "- 業種別空売り比率(/markets/short-ratio)\n", + "- 空売り残高報告(/markets/short-sale-report)\n", + "- 日々公表信用取引残高(/markets/margin-alert)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "cellView": "form", + "id": "JYj-j8BQecuF" + }, + "outputs": [], + "source": [ + "#@title 指数四本値(/indices/bars/daily)\n", + "\n", + "#@markdown - 日次の各種指数の四本値について取得することができます。\n", + "#@markdown - データの取得では、指数コード(code)または日付(date)の指定が必須となります。\n", + "\n", + "#@markdown (データ更新時刻)\n", + "#@markdown - 毎営業日の16:30頃\n", + "\n", + "\n", + "code = \"\"#@param {type:\"string\"}\n", + "date = \"\"#@param {type:\"string\"}\n", + "from_ = \"\" #@param {type:\"string\"}\n", + "to = \"\" #@param {type:\"string\"}\n", + "\n", + "params = {}\n", + "if code != \"\":\n", + " params[\"code\"] = code\n", + "if date != \"\":\n", + " params[\"date\"] = date\n", + "if from_ != \"\":\n", + " params[\"from\"] = from_\n", + "if to != \"\":\n", + " params[\"to\"] = to\n", + "\n", + "res = requests.get(f\"{API_URL}/indices/bars/daily\", params=params, headers=headers)\n", + "\n", + "if res.status_code == 200:\n", + " d = res.json()\n", + " data = d[\"data\"]\n", + " while \"pagination_key\" in d:\n", + " params[\"pagination_key\"] = d[\"pagination_key\"]\n", + " res = requests.get(f\"{API_URL}/indices/bars/daily\", params=params, headers=headers)\n", + " d = res.json()\n", + " data += d[\"data\"]\n", + " df = pd.DataFrame(data)\n", + " display(df)\n", + "else:\n", + " print(res.json())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "cellView": "form", + "id": "staIb4Xtr1it" + }, + "outputs": [], + "source": [ + "#@title 日経225オプション四本値(/derivatives/bars/daily/options/225)\n", + "\n", + "#@markdown - 日次の日経225指数オプションの四本値や売買高、清算値段等について取得することができます。\n", + "#@markdown - 日付(date)の指定が必須です\n", + "\n", + "#@markdown (データ更新時刻)\n", + "#@markdown - 毎営業日の27:00頃\n", + "\n", + "\n", + "date = \"\" #@param {type:\"string\"}\n", + "params = {}\n", + "if date != \"\":\n", + " params[\"date\"] = date\n", + "\n", + "res = requests.get(f\"{API_URL}/derivatives/bars/daily/options/225\", params=params, headers=headers)\n", + "\n", + "if res.status_code == 200:\n", + " d = res.json()\n", + " data = d[\"data\"]\n", + " while \"pagination_key\" in d:\n", + " params[\"pagination_key\"] = d[\"pagination_key\"]\n", + " res = requests.get(f\"{API_URL}/derivatives/bars/daily/options/225\", params=params, headers=headers)\n", + " d = res.json()\n", + " data += d[\"data\"]\n", + " df = pd.DataFrame(data)\n", + " display(df)\n", + "else:\n", + " print(res.json())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "cellView": "form", + "id": "sw-pwwYeP-ku" + }, + "outputs": [], + "source": [ + "#@title 信用取引週末残高(/markets/margin-interest)\n", + "\n", + "#@markdown - 制度・一般信用取引における各銘柄の前週末の残高についてデータを取得することができます。\n", + "#@markdown - 本データは[こちら](https://www.jpx.co.jp/markets/statistics-equities/margin/index.html)の個別銘柄信用取引残高表のデータをヒストリカルで提供するものになります。\n", + "#@markdown - 銘柄コード(code)もしくは日付(date)の指定が必須です。\n", + "#@markdown (From, Toはcodeを入れている場合にのみ可能)\n", + "\n", + "#@markdown (データ更新時刻)\n", + "#@markdown - 原則毎週第2営業日の16:30頃\n", + "\n", + "\n", + "code = \"\"#@param {type:\"string\"}\n", + "date = \"\"#@param {type:\"string\"}\n", + "from_ = \"\" #@param {type:\"string\"}\n", + "to = \"\" #@param {type:\"string\"}\n", + "\n", + "params = {}\n", + "if code != \"\":\n", + " params[\"code\"] = code\n", + "if date != \"\":\n", + " params[\"date\"] = date\n", + "if from_ != \"\":\n", + " params[\"from\"] = from_\n", + "if to != \"\":\n", + " params[\"to\"] = to\n", + "\n", + "res = requests.get(f\"{API_URL}/markets/margin-interest\", params=params, headers=headers)\n", + "\n", + "if res.status_code == 200:\n", + " d = res.json()\n", + " data = d[\"data\"]\n", + " while \"pagination_key\" in d:\n", + " params[\"pagination_key\"] = d[\"pagination_key\"]\n", + " res = requests.get(f\"{API_URL}/markets/margin-interest\", params=params, headers=headers)\n", + " d = res.json()\n", + " data += d[\"data\"]\n", + " df = pd.DataFrame(data)\n", + " display(df)\n", + "else:\n", + " print(res.json())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "cellView": "form", + "id": "DvqQfkf2r-U1" + }, + "outputs": [], + "source": [ + "#@title 業種別空売り比率(/markets/short-ratio)\n", + "\n", + "#@markdown - 日次の33業種別の空売りの売買代金について取得することができます。\n", + "#@markdown - 33業種コード(s33)もしくは日付(date)の指定が必須です。\n", + "#@markdown (From, Toはs33を入れている場合にのみ可能)\n", + "\n", + "#@markdown (データ更新時刻)\n", + "#@markdown - 毎営業日の16:30頃\n", + "\n", + "#@markdown (その他留意点)\n", + "#@markdown - 業種コード9999は、ETFやREIT等の33業種に含まれない銘柄のものになります。\n", + "\n", + "\n", + "s33 = \"\"#@param {type:\"string\"}\n", + "date = \"\"#@param {type:\"string\"}\n", + "from_ = \"\" #@param {type:\"string\"}\n", + "to = \"\" #@param {type:\"string\"}\n", + "\n", + "params = {}\n", + "if s33 != \"\":\n", + " params[\"s33\"] = s33\n", + "if date != \"\":\n", + " params[\"date\"] = date\n", + "if from_ != \"\":\n", + " params[\"from\"] = from_\n", + "if to != \"\":\n", + " params[\"to\"] = to\n", + "\n", + "res = requests.get(f\"{API_URL}/markets/short-ratio\", params=params, headers=headers)\n", + "\n", + "if res.status_code == 200:\n", + " d = res.json()\n", + " data = d[\"data\"]\n", + " while \"pagination_key\" in d:\n", + " params[\"pagination_key\"] = d[\"pagination_key\"]\n", + " res = requests.get(f\"{API_URL}/markets/short-ratio\", params=params, headers=headers)\n", + " d = res.json()\n", + " data += d[\"data\"]\n", + " df = pd.DataFrame(data)\n", + " display(df)\n", + "else:\n", + " print(res.json())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "Z-h3luGrayRO" + }, + "outputs": [], + "source": [ + "#@title 空売り残高報告(/markets/short-sale-report)\n", + "\n", + "#@markdown - 「有価証券の取引等の規制に関する内閣府令」に基づき、取引参加者より報告を受けたもののうち、残高割合が0.5%以上のものについての情報を取得できます。\n", + "#@markdown - データの取得では、銘柄コード(code)、公表日(disc_date)、計算日(calc_date)のいずれかの指定が必須となります。\n", + "\n", + "#@markdown (データ更新時刻)\n", + "#@markdown - 毎営業日の17:30頃\n", + "\n", + "code = \"\"#@param {type:\"string\"}\n", + "disc_date = \"\"#@param {type:\"string\"}\n", + "disc_date_from = \"\"#@param {type:\"string\"}\n", + "disc_date_to = \"\"#@param {type:\"string\"}\n", + "calc_date = \"\"#@param {type:\"string\"}\n", + "\n", + "params = {}\n", + "if code != \"\":\n", + " params[\"code\"] = code\n", + "if disc_date != \"\":\n", + " params[\"disc_date\"] = disc_date\n", + "if disc_date_from != \"\":\n", + " params[\"disc_date_from\"] = disc_date_from\n", + "if disc_date_to != \"\":\n", + " params[\"disc_date_to\"] = disc_date_to\n", + "if calc_date != \"\":\n", + " params[\"calc_date\"] = calc_date\n", + "\n", + "res = requests.get(f\"{API_URL}/markets/short-sale-report\", params=params, headers=headers)\n", + "\n", + "if res.status_code == 200:\n", + " d = res.json()\n", + " data = d[\"data\"]\n", + " while \"pagination_key\" in d:\n", + " params[\"pagination_key\"] = d[\"pagination_key\"]\n", + " res = requests.get(f\"{API_URL}/markets/short-sale-report\", params=params, headers=headers)\n", + " d = res.json()\n", + " data += d[\"data\"]\n", + " df = pd.DataFrame(data)\n", + " display(df)\n", + "else:\n", + " print(res.json())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "5y0CNrhCayRP" + }, + "outputs": [], + "source": [ + "#@title 日々公表信用取引残高(/markets/margin-alert)\n", + "\n", + "#@markdown - 東京証券取引所または日本証券金融が、日次の信用取引残高を公表する必要があると認めた銘柄のみが収録されます。\n", + "#@markdown - データの取得では、銘柄コード(code)、公表日(date)のいずれかの指定が必須となります。\n", + "\n", + "#@markdown (データ更新時刻)\n", + "#@markdown - 毎営業日の16:30頃\n", + "\n", + "code = \"\"#@param {type:\"string\"}\n", + "_date = \"\"#@param {type:\"string\"}\n", + "_from = \"\"#@param {type:\"string\"}\n", + "_to = \"\"#@param {type:\"string\"}\n", + "\n", + "params = {}\n", + "if code != \"\":\n", + " params[\"code\"] = code\n", + "if _date != \"\":\n", + " params[\"date\"] = _date\n", + "if _from != \"\":\n", + " params[\"from\"] = _from\n", + "if _to != \"\":\n", + " params[\"to\"] = _to\n", + "\n", + "res = requests.get(f\"{API_URL}/markets/margin-alert\", params=params, headers=headers)\n", + "\n", + "if res.status_code == 200:\n", + " d = res.json()\n", + " data = d[\"data\"]\n", + " while \"pagination_key\" in d:\n", + " params[\"pagination_key\"] = d[\"pagination_key\"]\n", + " res = requests.get(f\"{API_URL}/markets/margin-alert\", params=params, headers=headers)\n", + " d = res.json()\n", + " data += d[\"data\"]\n", + " df = pd.DataFrame(data)\n", + " display(df)\n", + "else:\n", + " print(res.json())" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "xB_u78xdqdem" + }, + "source": [ + "### Premiumプランで利用できるAPI\n", + "- 売買内訳データ(/markets/breakdown)\n", + "- 前場四本値(/equities/bars/daily/am)\n", + "- 配当金情報(/fins/dividend)\n", + "- 財務諸表(BS/PL/CF)(/fins/details)\n", + "- 先物四本値(/derivatives/bars/daily/futures)\n", + "- オプション四本値(/derivatives/bars/daily/options)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "cellView": "form", + "id": "KGQ-b4tEsPSs" + }, + "outputs": [], + "source": [ + "#@title 売買内訳データ(/markets/breakdown)\n", + "\n", + "#@markdown - 売買内訳データは、東証上場銘柄の東証市場における銘柄別の日次売買代金・売買高(立会内取引に限る)について、信用取引や空売りの利用に関して、発注時のフラグ情報を用いて細分化したデータです。\n", + "#@markdown - 銘柄コード(code)もしくは日付(date)の指定が必須です。\n", + "#@markdown (From, Toはcodeを入れている場合にのみ可能)\n", + "\n", + "#@markdown (データ更新時刻)\n", + "#@markdown - 毎営業日の18:00頃\n", + "\n", + "#@markdown (その他留意点)\n", + "#@markdown - 当日に立会内取引が成立しなかった場合(約定なし)、当該銘柄はレコードに含まれていません。\n", + "\n", + "code = \"\"#@param {type:\"string\"}\n", + "date = \"\"#@param {type:\"string\"}\n", + "from_ = \"\" #@param {type:\"string\"}\n", + "to = \"\" #@param {type:\"string\"}\n", + "\n", + "params = {}\n", + "if code != \"\":\n", + " params[\"code\"] = code\n", + "if date != \"\":\n", + " params[\"date\"] = date\n", + "if from_ != \"\":\n", + " params[\"from\"] = from_\n", + "if to != \"\":\n", + " params[\"to\"] = to\n", + "\n", + "res = requests.get(f\"{API_URL}/markets/breakdown\", params=params, headers=headers)\n", + "\n", + "if res.status_code == 200:\n", + " d = res.json()\n", + " data = d[\"data\"]\n", + " while \"pagination_key\" in d:\n", + " params[\"pagination_key\"] = d[\"pagination_key\"]\n", + " res = requests.get(f\"{API_URL}/markets/breakdown\", params=params, headers=headers)\n", + " d = res.json()\n", + " data += d[\"data\"]\n", + " df = pd.DataFrame(data)\n", + " display(df)\n", + "else:\n", + " print(res.json())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "cellView": "form", + "id": "URmkw7_gsTyl" + }, + "outputs": [], + "source": [ + "#@title 前場四本値(/equities/bars/daily/am)\n", + "\n", + "#@markdown - 各銘柄の前場の四本値及び取引高・代金について、当日の前場終了後のデータを取得できます。\n", + "#@markdown - 銘柄コード(code)を指定することができます。codeパラメータがない場合は、全銘柄取得されます。\n", + "\n", + "#@markdown (データ更新時刻)\n", + "#@markdown - 毎営業日の12:00頃\n", + "\n", + "#@markdown (その他留意点)\n", + "#@markdown - 本APIのデータは当日12:00頃〜翌日の朝6:00頃まで取得可能です。\n", + "#@markdown - 当日以外のヒストリカルのデータは、Premiumユーザの方は株価四本値(/equities/bars/daily)のAPIで取得可能です。\n", + "#@markdown - なお、上記以外の時間にAPIコールした場合は、StatusCode = 210が返却されます。(通常は200)\n", + "\n", + "\n", + "code = \"\"#@param {type:\"string\"}\n", + "\n", + "params = {}\n", + "if code != \"\":\n", + " params[\"code\"] = code\n", + "\n", + "res = requests.get(f\"{API_URL}/equities/bars/daily/am\", params=params, headers=headers)\n", + "\n", + "if res.status_code == 200:\n", + " d = res.json()\n", + " data = d[\"data\"]\n", + " while \"pagination_key\" in d:\n", + " params[\"pagination_key\"] = d[\"pagination_key\"]\n", + " res = requests.get(f\"{API_URL}/equities/bars/daily/am\", params=params, headers=headers)\n", + " d = res.json()\n", + " data += d[\"data\"]\n", + " df = pd.DataFrame(data)\n", + " display(df)\n", + "else:\n", + " print(res.json())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "cellView": "form", + "id": "vlAiQQhvRETA" + }, + "outputs": [], + "source": [ + "#@title 配当金情報(/fins/dividend)\n", + "\n", + "#@markdown - 上場会社の配当(決定・予想)に関する1株当たり配当金額、基準日、権利落日及び支払開始予定日等の情報が取得できます。\n", + "#@markdown - 銘柄コード(code)もしくは日付(date)の指定が必須です。\n", + "#@markdown (From, Toはcodeを入れている場合にのみ可能)\n", + "\n", + "#@markdown (データ更新時刻)\n", + "#@markdown - 毎営業日の19:00頃\n", + "\n", + "\n", + "code = \"\"#@param {type:\"string\"}\n", + "date = \"\"#@param {type:\"string\"}\n", + "from_ = \"\" #@param {type:\"string\"}\n", + "to = \"\" #@param {type:\"string\"}\n", + "\n", + "params = {}\n", + "if code != \"\":\n", + " params[\"code\"] = code\n", + "if date != \"\":\n", + " params[\"date\"] = date\n", + "if from_ != \"\":\n", + " params[\"from\"] = from_\n", + "if to != \"\":\n", + " params[\"to\"] = to\n", + "\n", + "res = requests.get(f\"{API_URL}/fins/dividend\", params=params, headers=headers)\n", + "\n", + "if res.status_code == 200:\n", + " d = res.json()\n", + " data = d[\"data\"]\n", + " while \"pagination_key\" in d:\n", + " params[\"pagination_key\"] = d[\"pagination_key\"]\n", + " res = requests.get(f\"{API_URL}/fins/dividend\", params=params, headers=headers)\n", + " d = res.json()\n", + " data += d[\"data\"]\n", + " df = pd.DataFrame(data)\n", + " display(df)\n", + "else:\n", + " print(res.json())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "cellView": "form", + "id": "wB4e2I4jdzGK" + }, + "outputs": [], + "source": [ + "#@title 財務諸表(BS/PL/CF)(/fins/details)\n", + "\n", + "#@markdown - 財務諸表(BS/PL/CF)APIでは、上場企業の四半期毎の財務情報における、貸借対照表、損益計算書に記載の項目を取得することができます。\n", + "#@markdown - 本コードでは、出力結果の表示方法をformat_typeを指定して切り替え可能です。flat:全項目をヘッダーに表示する、non-flat:詳細項目を1列に集約します。\n", + "#@markdown - データの取得では、銘柄コード(code)または開示日(date)の指定が必須です。\n", + "\n", + "#@markdown (データ更新時刻)\n", + "#@markdown - 速報18:00頃、確報24:30頃\n", + "\n", + "\n", + "format_type = \"non-flat\"#@param [\"non-flat\", \"flat\"]\n", + "code = \"\"#@param {type:\"string\"}\n", + "date = \"\"#@param {type:\"string\"}\n", + "\n", + "params = {}\n", + "if code != \"\":\n", + " params[\"code\"] = code\n", + "if date != \"\":\n", + " params[\"date\"] = date\n", + "\n", + "res = requests.get(f\"{API_URL}/fins/details\", params=params, headers=headers)\n", + "\n", + "if res.status_code == 200:\n", + " d = res.json()\n", + " data = d[\"data\"]\n", + " while \"pagination_key\" in d:\n", + " params[\"pagination_key\"] = d[\"pagination_key\"]\n", + " res = requests.get(f\"{API_URL}/fins/details\", params=params, headers=headers)\n", + " d = res.json()\n", + " data += d[\"data\"]\n", + " if format_type == \"non-flat\":\n", + " df = pd.DataFrame(data)\n", + " else:\n", + " df = pd.json_normalize(data)\n", + " display(df)\n", + "else:\n", + " print(res.json())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "hy9SP_3mayRQ" + }, + "outputs": [], + "source": [ + "#@title 先物四本値(/derivatives/bars/daily/futures)\n", + "\n", + "#@markdown - 先物四本値APIでは、先物に関する、四本値や清算値段、理論価格に関する情報を取得することができます。\n", + "#@markdown - データの取得では、日付(date)の指定が必須です。\n", + "\n", + "#@markdown (データ更新時刻)\n", + "#@markdown - 毎営業日の27:00頃\n", + "\n", + "category = \"\"#@param {type:\"string\"}\n", + "date = \"\"#@param {type:\"string\"}\n", + "contract_flag = \"\"#@param{type:\"string\"}\n", + "\n", + "params = {}\n", + "if category != \"\":\n", + " params[\"category\"] = category\n", + "if date != \"\":\n", + " params[\"date\"] = date\n", + "if contract_flag != \"\":\n", + " params[\"contract_flag\"] = contract_flag\n", + "\n", + "res = requests.get(f\"{API_URL}/derivatives/bars/daily/futures\", params=params, headers=headers)\n", + "\n", + "if res.status_code == 200:\n", + " d = res.json()\n", + " data = d[\"data\"]\n", + " while \"pagination_key\" in d:\n", + " params[\"pagination_key\"] = d[\"pagination_key\"]\n", + " res = requests.get(f\"{API_URL}/derivatives/bars/daily/futures\", params=params, headers=headers)\n", + " d = res.json()\n", + " data += d[\"data\"]\n", + " df = pd.DataFrame(data)\n", + " display(df)\n", + "else:\n", + " print(res.json())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "Ma1o-sliayRQ" + }, + "outputs": [], + "source": [ + "#@title オプション四本値(/derivatives/bars/daily/options)\n", + "\n", + "#@markdown - オプション四本値APIでは、オプションに関する、四本値や清算値段、理論価格に関する情報を取得することができます。\n", + "#@markdown - データの取得では、日付(date)の指定が必須です。\n", + "\n", + "#@markdown (データ更新時刻)\n", + "#@markdown - 毎営業日の27:00頃\n", + "\n", + "category = \"\"#@param {type:\"string\"}\n", + "date = \"\"#@param {type:\"string\"}\n", + "contract_flag = \"\"#@param{type:\"string\"}\n", + "\n", + "params = {}\n", + "if category != \"\":\n", + " params[\"category\"] = category\n", + "if date != \"\":\n", + " params[\"date\"] = date\n", + "if contract_flag != \"\":\n", + " params[\"contract_flag\"] = contract_flag\n", + "\n", + "res = requests.get(f\"{API_URL}/derivatives/bars/daily/options\", params=params, headers=headers)\n", + "\n", + "if res.status_code == 200:\n", + " d = res.json()\n", + " data = d[\"data\"]\n", + " while \"pagination_key\" in d:\n", + " params[\"pagination_key\"] = d[\"pagination_key\"]\n", + " res = requests.get(f\"{API_URL}/derivatives/bars/daily/options\", params=params, headers=headers)\n", + " d = res.json()\n", + " data += d[\"data\"]\n", + " df = pd.DataFrame(data)\n", + " display(df)\n", + "else:\n", + " print(res.json())" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "wu3WbdMTayRR" + }, + "source": [ + "### Bulk API(CSVダウンロード)\n", + "- ダウンロード可能ファイル一覧(/bulk/list)\n", + "- ファイルダウンロード用URL取得(/bulk/get)\n", + "\n", + "Bulk APIを使用すると、CSV形式で大量のデータを効率的にダウンロードできます。\n", + "**Lightプラン以上**で利用できます(Freeプランでは取引カレンダー(/markets/calendar)のCSVのみ取得可能です)。\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "3LS7Z8mhayRR" + }, + "outputs": [], + "source": [ + "#@title ダウンロード可能ファイル一覧(/bulk/list)\n", + "\n", + "#@markdown - CSV形式でダウンロード可能なファイルの一覧を取得するエンドポイントです。\n", + "#@markdown - endpointパラメータで取得したいデータセットを指定します。\n", + "\n", + "#@markdown (指定可能なendpoint例)\n", + "#@markdown - /equities/bars/daily(株価四本値)\n", + "#@markdown - /equities/bars/minute(株価分足)\n", + "#@markdown - /fins/summary(財務情報)\n", + "#@markdown - /indices/bars/daily/topix(TOPIX指数四本値)\n", + "#@markdown - など\n", + "\n", + "#@markdown 指定可能なendpointの完全な一覧は[こちら](https://jpx-jquants.com/ja/spec/bulk-list/endpoints)をご覧ください。\n", + "\n", + "endpoint = \"/equities/bars/daily\"#@param {type:\"string\"}\n", + "\n", + "params = {}\n", + "if endpoint != \"\":\n", + " params[\"endpoint\"] = endpoint\n", + "\n", + "res = requests.get(f\"{API_URL}/bulk/list\", params=params, headers=headers)\n", + "\n", + "if res.status_code == 200:\n", + " d = res.json()\n", + " data = d[\"data\"]\n", + " df = pd.DataFrame(data)\n", + " display(df)\n", + "else:\n", + " print(res.json())\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "YL3VK61HayRR" + }, + "outputs": [], + "source": [ + "#@title ファイルダウンロード用URL取得(/bulk/get)\n", + "\n", + "#@markdown - /bulk/list で取得したKeyを指定して、CSVファイルダウンロード用の署名付きURLを取得します。\n", + "#@markdown - 取得したURLの有効期限は約5分です。期限内にダウンロードを完了してください。\n", + "\n", + "#@markdown (使い方)\n", + "#@markdown 1. まず /bulk/list でダウンロード可能なファイル一覧を取得\n", + "#@markdown 2. 取得したファイル一覧からダウンロードしたいファイルの Key を確認\n", + "#@markdown 3. その Key を下記に入力して実行\n", + "#@markdown 4. 取得したURLにアクセスしてCSVをダウンロード\n", + "\n", + "key = \"\"#@param {type:\"string\"}\n", + "\n", + "params = {}\n", + "if key != \"\":\n", + " params[\"key\"] = key\n", + "\n", + "res = requests.get(f\"{API_URL}/bulk/get\", params=params, headers=headers)\n", + "\n", + "if res.status_code == 200:\n", + " d = res.json()\n", + " download_url = d.get(\"url\", \"\")\n", + " print(\"ダウンロードURL(有効期限: 約5分):\")\n", + " print(download_url)\n", + " print(\"\\n※ 上記URLにアクセスしてCSVファイルをダウンロードしてください。\")\n", + "else:\n", + " print(res.json())\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "oB--a6tTayRS" + }, + "outputs": [], + "source": [ + "#@title Bulk APIを組み合わせた実行例(list → get)\n", + "\n", + "#@markdown - /bulk/list でファイル一覧を取得し、特定のファイルの Key を使って /bulk/get でダウンロードURLを取得する実行例です。\n", + "\n", + "#@markdown (使い方)\n", + "#@markdown 1. endpoint に取得したいデータセットのエンドポイントを指定\n", + "#@markdown 2. num_files に取得したいファイルの件数を指定(デフォルト: 3件)\n", + "#@markdown 3. 実行するとファイル一覧が表示されます\n", + "#@markdown 4. 一覧の中から指定された件数分のファイルの Key を取得し、ダウンロードURLを取得\n", + "\n", + "endpoint = \"/equities/bars/daily\"#@param {type:\"string\"}\n", + "num_files = 3#@param {type:\"integer\"}\n", + "\n", + "# Step 1: ファイル一覧を取得\n", + "params = {\"endpoint\": endpoint}\n", + "res = requests.get(f\"{API_URL}/bulk/list\", params=params, headers=headers)\n", + "\n", + "if res.status_code == 200:\n", + " d = res.json()\n", + " files = d[\"data\"]\n", + " df_files = pd.DataFrame(files)\n", + "\n", + " print(\"=== 利用可能なファイル一覧 ===\")\n", + " display(df_files)\n", + "\n", + " if len(files) > 0:\n", + " # 指定された件数分のファイルのKeyを取得(最大でファイル数まで)\n", + " target_count = min(num_files, len(files))\n", + " print(f\"\\n{target_count}件のファイルのダウンロードURLを取得します...\")\n", + "\n", + " # Step 2: 各ファイルのダウンロードURLを取得\n", + " for i in range(target_count):\n", + " file_key = files[i][\"Key\"]\n", + " print(f\"\\n--- ファイル {i+1}/{target_count} ---\")\n", + " print(f\"Key: {file_key}\")\n", + "\n", + " params_get = {\"key\": file_key}\n", + " res_get = requests.get(f\"{API_URL}/bulk/get\", params=params_get, headers=headers)\n", + "\n", + " if res_get.status_code == 200:\n", + " d_get = res_get.json()\n", + " download_url = d_get.get(\"url\", \"\")\n", + " print(f\"URL(有効期限: 約5分):\")\n", + " print(download_url)\n", + " else:\n", + " print(\"ダウンロードURL取得エラー:\")\n", + " print(res_get.json())\n", + "\n", + " print(\"\\n※ 上記URLにアクセスしてCSVファイルをダウンロードしてください。\")\n", + " else:\n", + " print(\"\\n利用可能なファイルがありません。\")\n", + "else:\n", + " print(\"ファイル一覧取得エラー:\")\n", + " print(res.json())" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "J7MtC58sayRU" + }, + "source": [ + "### Lightプラン以上 + アドオン契約で利用できるAPI(株価 分足・ティック)\n", + "- 株価分足(/equities/bars/minute)\n", + "\n", + "\\* 株価 分足・ティック アドオンの契約が必要です。データ取得可能期間は過去2年間です。\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "LTgoL8oTayRU" + }, + "outputs": [], + "source": [ + "#@title 株価分足(/equities/bars/minute)\n", + "\n", + "#@markdown - 分足の株価データを取得するエンドポイント。1分単位の四本値(始値・高値・安値・終値)、出来高、売買代金のデータを取得できます。\n", + "#@markdown - データの取得では、銘柄コード(code)または日付(date)の指定が必須となります。\n", + "#@markdown - データ取得可能期間は過去2年間です。\n", + "\n", + "#@markdown (データ更新時刻)\n", + "#@markdown - 毎営業日の16:30頃\n", + "\n", + "#@markdown (その他留意点)\n", + "#@markdown - 株価 分足・ティック アドオンの契約が必要です。\n", + "#@markdown - 全銘柄のデータを一括取得する場合は、Bulk APIの使用を推奨します。\n", + "\n", + "code = \"\"#@param {type:\"string\"}\n", + "date = \"20250122\"#@param {type:\"string\"}\n", + "from_ = \"\" #@param {type:\"string\"}\n", + "to = \"\" #@param {type:\"string\"}\n", + "\n", + "params = {}\n", + "if code != \"\":\n", + " params[\"code\"] = code\n", + "if date != \"\":\n", + " params[\"date\"] = date\n", + "if from_ != \"\":\n", + " params[\"from\"] = from_\n", + "if to != \"\":\n", + " params[\"to\"] = to\n", + "\n", + "res = requests.get(f\"{API_URL}/equities/bars/minute\", params=params, headers=headers)\n", + "\n", + "if res.status_code == 200:\n", + " d = res.json()\n", + " data = d[\"data\"]\n", + " while \"pagination_key\" in d:\n", + " params[\"pagination_key\"] = d[\"pagination_key\"]\n", + " res = requests.get(f\"{API_URL}/equities/bars/minute\", params=params, headers=headers)\n", + " d = res.json()\n", + " data += d[\"data\"]\n", + " df = pd.DataFrame(data)\n", + " display(df)\n", + "else:\n", + " print(res.json())\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "265a80a4" + }, + "source": [ + "### Lightプラン以上 + アドオン契約で利用できるAPI(TDnet/適時開示情報)\n", + "- 適時開示インデックス一覧(/td/list)\n", + "- 適時開示ファイルダウンロードURL取得(/td/files)\n", + "- 適時開示インデックス一括ダウンロード(/td/bulk)\n", + "\n", + "\\* **TDnet/適時開示情報アドオン**の契約が必要です。データ取得可能期間は過去5年間です。\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "33d0c5ce" + }, + "outputs": [], + "source": [ + "#@title 適時開示インデックス一覧(/td/list)\n", + "\n", + "#@markdown - 適時開示のインデックス情報(開示番号・日時・タイトルなど)の一覧を取得できます。\n", + "#@markdown - `date`(開示日)または `code`(銘柄コード)のいずれかを必ず指定してください。\n", + "#@markdown - `date` に当日を指定して `cursor` を使い回すことで、新着開示情報をセミリアルタイムに取得できます。\n", + "\n", + "#@markdown (パラメータ例)\n", + "#@markdown - date: 取得したい開示日(例: 20250401)\n", + "#@markdown - code: 銘柄コード(例: 86970 または 8697)\n", + "#@markdown - from/to: code と組み合わせた期間指定(例: from=20250101 to=20250401)\n", + "#@markdown - discItems: 公開項目コードで絞り込み(カンマ区切り)\n", + "#@markdown - cursor: 前回レスポンスの cursor 値(date と組み合わせて使用、前回取得以降の新規開示を取得)\n", + "\n", + "date = \"20250401\"#@param {type:\"string\"}\n", + "code = \"\"#@param {type:\"string\"}\n", + "from_date = \"\"#@param {type:\"string\"}\n", + "to_date = \"\"#@param {type:\"string\"}\n", + "disc_items = \"\"#@param {type:\"string\"}\n", + "cursor = \"\"#@param {type:\"string\"}\n", + "\n", + "params = {}\n", + "if date != \"\":\n", + " params[\"date\"] = date\n", + "if code != \"\":\n", + " params[\"code\"] = code\n", + "if from_date != \"\":\n", + " params[\"from\"] = from_date\n", + "if to_date != \"\":\n", + " params[\"to\"] = to_date\n", + "if disc_items != \"\":\n", + " params[\"discItems\"] = disc_items\n", + "if cursor != \"\":\n", + " params[\"cursor\"] = cursor\n", + "\n", + "all_data = []\n", + "cursor_value = None\n", + "pagination_key = None\n", + "\n", + "while True:\n", + " request_params = dict(params)\n", + " if pagination_key:\n", + " request_params[\"pagination_key\"] = pagination_key\n", + "\n", + " res = requests.get(f\"{API_URL}/td/list\", params=request_params, headers=headers)\n", + "\n", + " if res.status_code != 200:\n", + " print(res.json())\n", + " break\n", + "\n", + " d = res.json()\n", + " all_data.extend(d.get(\"data\", []))\n", + "\n", + " if \"cursor\" in d:\n", + " cursor_value = d[\"cursor\"]\n", + "\n", + " pagination_key = d.get(\"pagination_key\")\n", + " if not pagination_key:\n", + " break\n", + "\n", + "if all_data:\n", + " df = pd.DataFrame(all_data)\n", + " display(df)\n", + "\n", + "if cursor_value:\n", + " print(f\"\\ncursor(次回取得用): {cursor_value}\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "22dfd6ff" + }, + "outputs": [], + "source": [ + "#@title 適時開示ファイルダウンロードURL取得(/td/files)\n", + "\n", + "#@markdown - 開示番号(discNo)に対応するファイル(PDF / XBRL)のダウンロードURLを取得します。\n", + "#@markdown - /td/list で取得した DiscNo を discNo に入力してください。\n", + "#@markdown - 取得したURLの有効期限は15分です。\n", + "\n", + "#@markdown (docs パラメータで取得ファイル種別を絞り込めます)\n", + "#@markdown - g: 全文情報PDF\n", + "#@markdown - s: サマリ情報PDF\n", + "#@markdown - x: XBRL関連ファイル\n", + "#@markdown - 省略時は全種類を返します(例: g,s,x)\n", + "\n", + "disc_no = \"20250401130100\"#@param {type:\"string\"}\n", + "docs = \"\"#@param {type:\"string\"}\n", + "\n", + "params = {}\n", + "if disc_no != \"\":\n", + " params[\"discNo\"] = disc_no\n", + "if docs != \"\":\n", + " params[\"docs\"] = docs\n", + "\n", + "res = requests.get(f\"{API_URL}/td/files\", params=params, headers=headers)\n", + "\n", + "if res.status_code == 200:\n", + " d = res.json()\n", + " print(f\"開示番号: {d.get('discNo')}\")\n", + " files = d.get(\"files\")\n", + " if files:\n", + " for key, url in files.items():\n", + " print(f\"\\n{key}(有効期限: 15分):\")\n", + " print(url)\n", + " else:\n", + " print(\"ファイルが見つかりませんでした。\")\n", + "else:\n", + " print(res.json())\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "7a73c454" + }, + "outputs": [], + "source": [ + "#@title 適時開示インデックス一括ダウンロード(/td/bulk)\n", + "\n", + "#@markdown - 過去5年分の適時開示インデックス情報をまとめたCSV(gzip圧縮)のダウンロードURLを取得します。\n", + "#@markdown - 取得したURLの有効期限は15分です。期限内にダウンロードを完了してください。\n", + "\n", + "#@markdown (使い方)\n", + "#@markdown 1. 実行するとCSVファイルのダウンロードURLと最終更新日時が表示されます\n", + "#@markdown 2. 取得したURLにアクセスしてCSV(gzip形式)をダウンロード\n", + "#@markdown 3. CSVを解凍して開示情報を取得\n", + "\n", + "import io\n", + "import gzip\n", + "\n", + "res = requests.get(f\"{API_URL}/td/bulk\", headers=headers)\n", + "\n", + "if res.status_code == 200:\n", + " d = res.json()\n", + " last_updated = d.get(\"lastUpdated\", \"\")\n", + " download_url = d.get(\"url\", \"\")\n", + " print(f\"最終更新日時: {last_updated}\")\n", + " print(f\"\\nダウンロードURL(有効期限: 15分):\")\n", + " print(download_url)\n", + "\n", + " # ダウンロードしてDataFrameに読み込む例\n", + " if download_url:\n", + " print(\"\\nCSVをダウンロードしてDataFrameに読み込み中...\")\n", + " csv_res = requests.get(download_url)\n", + " if csv_res.status_code == 200:\n", + " with gzip.open(io.BytesIO(csv_res.content), \"rt\", encoding=\"utf-8\") as f:\n", + " df = pd.read_csv(f)\n", + " print(f\"取得件数: {len(df)} 件\")\n", + " display(df.head())\n", + " else:\n", + " print(f\"ダウンロードエラー: {csv_res.status_code}\")\n", + "else:\n", + " print(res.json())\n" + ] + } + ], + "metadata": { + "colab": { + "provenance": [], + "include_colab_link": true + }, + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.13" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} \ No newline at end of file diff --git a/src/MarlinSimulator/hardware/KinematicSystem.cpp b/src/MarlinSimulator/hardware/KinematicSystem.cpp index c69f388..21b119e 100644 --- a/src/MarlinSimulator/hardware/KinematicSystem.cpp +++ b/src/MarlinSimulator/hardware/KinematicSystem.cpp @@ -413,3 +413,97 @@ void DeltaKinematicSystem::ui_widget() { ImGui::Text("y: %f", state.effector_position[0].position.y); ImGui::Text("z: %f", state.effector_position[0].position.z); } + +#if ENABLED(MP_SCARA) + +ScaraKinematicSystem::ScaraKinematicSystem(std::function on_kinematic_update) : KinematicSystem(on_kinematic_update) { + collect_steppers(); + // if defined MP_SCARA it means degrees of arms when nozzle is at (0,0,z) position + // when SCARA_LINKAGE_1 = 250mm, SCARA_LINKAGE_2 = 250mm, SCARA_OFFSET_X = 75mm, SCARA_OFFSET_Y = -100mm + // you can calculate the degrees with following method which is copyed from Marlin-bugfix-2.1.x + /* + static constexpr xy_pos_t scara_offset = { SCARA_OFFSET_X, SCARA_OFFSET_Y }; + float constexpr L1 = SCARA_LINKAGE_1, L2 = SCARA_LINKAGE_2; + void inverse_kinematics(const xyz_pos_t &raw) { + // Translate SCARA to standard XY with scaling factor + const xy_pos_t spos = raw - scara_offset; + const float x = spos.x, y = spos.y, c = HYPOT(x, y), + THETA3 = ATAN2(y, x), + THETA1 = THETA3 + ACOS((sq(c) + sq(L1) - sq(L2)) / (2.0f * c * L1)), + THETA2 = THETA3 - ACOS((sq(c) + sq(L2) - sq(L1)) / (2.0f * c * L2)); + + delta.set(DEGREES(THETA1), DEGREES(THETA2), raw.z); + } + */ + hardware_offset.push_back({ 202.39, 51.35, 0.0 }); +} + +glm::vec3 ScaraKinematicSystem::forward_kinematics(const double a, const double b, const double z) { + const float a_sin = std::sin(glm::radians(a)) * SCARA_LINKAGE_1, + a_cos = std::cos(glm::radians(a)) * SCARA_LINKAGE_1, + b_sin = std::sin(glm::radians(b)) * SCARA_LINKAGE_2, + b_cos = std::cos(glm::radians(b)) * SCARA_LINKAGE_2; + + // return the pos to the position of Tower + + return glm::vec3{ a_cos + b_cos + SCARA_OFFSET_X, + a_sin + b_sin + SCARA_OFFSET_Y, + z}; +} + +void ScaraKinematicSystem::kinematic_update() { + auto carriage = glm::vec3{ + std::static_pointer_cast(steppers[AxisIndex::X])->steps() / steps_per_unit[0] * (((INVERT_X_DIR * 2) - 1) * -1.0), + std::static_pointer_cast(steppers[AxisIndex::Y])->steps() / steps_per_unit[1] * (((INVERT_Y_DIR * 2) - 1) * -1.0), + std::static_pointer_cast(steppers[AxisIndex::Z])->steps() / steps_per_unit[2] * (((INVERT_Z_DIR * 2) - 1) * -1.0) + }; + + extruder.clear(); + for (size_t i = 0; i < EXTRUDERS; ++i) { + extruder.push_back(std::static_pointer_cast(steppers[AxisIndex::E0 + i])->steps() / steps_per_unit[3 + (i * distinct_e_factors)] * (((extruder_invert_dir[i] * 2) - 1) * -1.0)); + } + double a = hardware_offset[0].x + carriage.x; + double b = hardware_offset[0].y + carriage.y; + auto cartesian_pos = forward_kinematics(a, b, hardware_offset[0].z + carriage.z); + + + for (size_t i = 0; i < HOTENDS; ++i) { + state.effector_position[i] = {carriage, glm::vec4(cartesian_pos, extruder[i]), filament_color[i]}; + } + + state.position = state.effector_position[0].position; + state.arm_angle.clear(); + state.arm_angle.push_back(a); + state.arm_angle.push_back(b); + on_kinematic_update(state); +} + +void ScaraKinematicSystem::ui_widget() { + if (state.effector_position.size() > 0) { + auto value = hardware_offset[0].x + state.effector_position[0].stepper_position.x; + if (ImGui::SliderFloat("hardware(a) offset (deg)", &value, -360, 360)) { + hardware_offset[0].x = value - state.effector_position[0].stepper_position.x; + kinematic_update(); + } + value = hardware_offset[0].y + state.effector_position[0].stepper_position.y; + if (ImGui::SliderFloat("hardware(b) offset (deg)", &value, -360, 360)) { + hardware_offset[0].y = value - state.effector_position[0].stepper_position.y; + kinematic_update(); + } + value = hardware_offset[0].z + state.effector_position[0].stepper_position.z; + if (ImGui::SliderFloat("hardware(z) offset (mm)", &value, -10, 100)) { + hardware_offset[0].z = value - state.effector_position[0].stepper_position.z; + kinematic_update(); + } + ImGui::Text("Stepper Position:"); + ImGui::Text("x: %f", state.effector_position[0].stepper_position.x); + ImGui::Text("y: %f", state.effector_position[0].stepper_position.y); + ImGui::Text("z: %f", state.effector_position[0].stepper_position.z); + ImGui::Text("Cartesian Position:"); + ImGui::Text("x: %f", state.effector_position[0].position.x); + ImGui::Text("y: %f", state.effector_position[0].position.y); + ImGui::Text("z: %f", state.effector_position[0].position.z); + } +} + +#endif \ No newline at end of file diff --git a/src/MarlinSimulator/hardware/KinematicSystem.h b/src/MarlinSimulator/hardware/KinematicSystem.h index f37513d..358b76a 100644 --- a/src/MarlinSimulator/hardware/KinematicSystem.h +++ b/src/MarlinSimulator/hardware/KinematicSystem.h @@ -3,7 +3,6 @@ #include #include #include - #include #include "Gpio.h" @@ -19,6 +18,9 @@ struct extruder_state { struct kinematic_state { std::vector effector_position {}; glm::vec3 position {}; +#if ENABLED(MP_SCARA) + std::vector arm_angle {}; +#endif }; class KinematicSystem : public VirtualPrinter::Component { @@ -60,3 +62,15 @@ class DeltaKinematicSystem : public KinematicSystem { glm::vec3 forward_kinematics(const double z1, const double z2, const double z3); void recalc_delta_settings(); }; + +#if ENABLED(MP_SCARA) +class ScaraKinematicSystem : public KinematicSystem { +public: + ScaraKinematicSystem(std::function on_kinematic_update); + virtual void ui_widget() override; + virtual void kinematic_update() override; + glm::vec3 forward_kinematics(const double a, const double b, const double z); + std::vector hardware_offset {}; + std::vector extruder {}; +}; +#endif \ No newline at end of file diff --git a/src/MarlinSimulator/hardware/ScaraArm.h b/src/MarlinSimulator/hardware/ScaraArm.h new file mode 100644 index 0000000..c32e0f7 --- /dev/null +++ b/src/MarlinSimulator/hardware/ScaraArm.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +#include "../virtual_printer.h" + +class ScaraArm : public VirtualPrinter::Component { +public: + ScaraArm() : VirtualPrinter::Component("ScaraArm") { + + } + ~ScaraArm() {} + + void ui_widget() { + ImGui::Checkbox("Enabled", &enabled); + } + + bool enabled = true; +}; \ No newline at end of file diff --git a/src/MarlinSimulator/virtual_printer.cpp b/src/MarlinSimulator/virtual_printer.cpp index f6ce50a..0d6f22e 100644 --- a/src/MarlinSimulator/virtual_printer.cpp +++ b/src/MarlinSimulator/virtual_printer.cpp @@ -16,6 +16,7 @@ #include "hardware/NeoPixelDevice.h" #include "hardware/KinematicSystem.h" #include "hardware/pwm_reader.h" +#include "hardware/ScaraArm.h" #include "virtual_printer.h" @@ -26,6 +27,10 @@ #include MARLIN_HAL_PATH(tft/xpt2046.h) #endif +#ifndef SD_DETECT_PIN + #define SD_DETECT_PIN -1 +#endif + #ifndef SD_DETECT_STATE #define SD_DETECT_STATE HIGH #endif @@ -51,7 +56,10 @@ void VirtualPrinter::Component::ui_widgets() { void VirtualPrinter::build() { root = add_component("root"); - #if ENABLED(DELTA) + #if ENABLED(MP_SCARA) + auto kinematics = root->add_component("MP Scara Kinematic System", on_kinematic_update); + root->add_component("ScaraArm"); + #elif ENABLED(DELTA) auto kinematics = root->add_component("Delta Kinematic System", on_kinematic_update); root->add_component("Endstop(Tower A Max)", X_MAX_PIN, !X_MAX_ENDSTOP_HIT_STATE, [kinematics](){ return kinematics->state.effector_position[0].stepper_position.x >= DELTA_HEIGHT; }); root->add_component("Endstop(Tower B Max)", Y_MAX_PIN, !Y_MAX_ENDSTOP_HIT_STATE, [kinematics](){ return kinematics->state.effector_position[0].stepper_position.y >= DELTA_HEIGHT; }); diff --git a/src/MarlinSimulator/visualisation.cpp b/src/MarlinSimulator/visualisation.cpp index 47c0912..bbb1c58 100644 --- a/src/MarlinSimulator/visualisation.cpp +++ b/src/MarlinSimulator/visualisation.cpp @@ -19,17 +19,84 @@ Visualisation::Visualisation(VirtualPrinter& virtual_printer) : virtual_printer( for (size_t i = 0; i < state.effector_position.size(); ++i) { this->set_head_position(i, state.effector_position[i]); } + #if ENABLED(MP_SCARA) + if(state.arm_angle.size() == 2){ + arm_angle_changed = false; + for (size_t i = 0; i < state.arm_angle.size(); ++i) { + if(this->arm_angle[i] != state.arm_angle[i]) + this->arm_angle[i] = state.arm_angle[i]; + arm_angle_changed = true; + } + } + #endif }; for (int i = 0; i < EXTRUDERS; ++i) { extrusion.push_back({}); } +#if ENABLED(MP_SCARA) + arm_angle.push_back({}); + arm_angle.push_back({}); +#endif } Visualisation::~Visualisation() { destroy(); } +renderer::mesh_id_t Visualisation::scara_add_mesh_arm(const double link_length) +{ + auto mesh_arm = renderer::create_mesh(); + auto buffer_arm = renderer::Buffer::create(); + float arm_L = link_length; + float arm_W = arm_L/100; + float arm_H = arm_L/100; + float x = -arm_W/2; + float y = arm_H/2; + float z = arm_L; + + buffer_arm->data() = { + //top + renderer::vertex_data_t EFFECTOR_VERTEX(0, y, x, EFFECTOR_COLOR_2), + EFFECTOR_VERTEX(0, y, -x, EFFECTOR_COLOR_2), + EFFECTOR_VERTEX(z, y, -x, EFFECTOR_COLOR_2), + + EFFECTOR_VERTEX(z, y, x, EFFECTOR_COLOR_2), + EFFECTOR_VERTEX(0, y, x, EFFECTOR_COLOR_2), + EFFECTOR_VERTEX(z, y, -x, EFFECTOR_COLOR_2), + + //left + EFFECTOR_VERTEX(0, -y, x, EFFECTOR_COLOR_2), + EFFECTOR_VERTEX(0, y, x, EFFECTOR_COLOR_2), + EFFECTOR_VERTEX(z, y, x, EFFECTOR_COLOR_2), + + EFFECTOR_VERTEX(z, y, x, EFFECTOR_COLOR_2), + EFFECTOR_VERTEX(z, -y, x, EFFECTOR_COLOR_2), + EFFECTOR_VERTEX(0, -y, x, EFFECTOR_COLOR_2), + + //right + EFFECTOR_VERTEX(0, y, -x, EFFECTOR_COLOR_2), + EFFECTOR_VERTEX(0, -y, -x, EFFECTOR_COLOR_2), + EFFECTOR_VERTEX(z, -y, -x, EFFECTOR_COLOR_2), + + EFFECTOR_VERTEX(z, -y, -x, EFFECTOR_COLOR_2), + EFFECTOR_VERTEX(z, y, -x, EFFECTOR_COLOR_2), + EFFECTOR_VERTEX(0, y, -x, EFFECTOR_COLOR_2), + + //front + EFFECTOR_VERTEX(0, y, x, EFFECTOR_COLOR_2), + EFFECTOR_VERTEX(0, -y, x, EFFECTOR_COLOR_2), + EFFECTOR_VERTEX(0, -y, -x, EFFECTOR_COLOR_2), + + EFFECTOR_VERTEX(0, -y, -x, EFFECTOR_COLOR_2), + EFFECTOR_VERTEX(0, -y, x, EFFECTOR_COLOR_2), + EFFECTOR_VERTEX(0, y, x, EFFECTOR_COLOR_2) + }; + renderer::get_mesh_by_id(mesh_arm)->buffer_vector().push_back(buffer_arm); + renderer::get_mesh_by_id(mesh_arm)->set_shader_program(default_program); + return mesh_arm; +} + void Visualisation::create() { extrusion_program = renderer::ShaderProgram::create("data/shaders/extrusion.vs", "data/shaders/extrusion.fs", "data/shaders/extrusion.gs"); default_program = renderer::ShaderProgram::create("data/shaders/default.vs","data/shaders/default.fs"); @@ -83,7 +150,11 @@ void Visualisation::create() { mesh_object->set_shader_program(default_program); mesh_object->m_scale = effector_scale; } - +#if ENABLED(MP_SCARA) +// add scara arms + m_arm_mesh.push_back(scara_add_mesh_arm(SCARA_LINKAGE_1)); + m_arm_mesh.push_back(scara_add_mesh_arm(SCARA_LINKAGE_2)); +#endif m_bed_mesh = renderer::create_mesh(); auto mesh_object = renderer::get_mesh_by_id(m_bed_mesh); mesh_object->set_shader_program(default_program); @@ -123,6 +194,7 @@ void Visualisation::create() { auto kin = virtual_printer.get_component("Cartesian Kinematic System"); if(kin == nullptr) kin = virtual_printer.get_component("Delta Kinematic System"); + if(kin == nullptr) kin = virtual_printer.get_component("MP Scara Kinematic System"); if (kin != nullptr && kin->state.effector_position.size() == extrusion.size()) { size_t i = 0; for (auto state : kin->state.effector_position) { @@ -137,6 +209,11 @@ void Visualisation::create() { for (auto mesh : m_extruder_mesh) { renderer::render_mesh(mesh); } +#if ENABLED(MP_SCARA) + for (auto mesh : m_arm_mesh) { + renderer::render_mesh(mesh); + } +#endif renderer::render_list_is_ready(); m_initialised = true; } @@ -234,12 +311,43 @@ void Visualisation::update() { mesh_id ++; } - +#if ENABLED(MP_SCARA) + auto scara_arm = virtual_printer.get_component("ScaraArm"); + // update the position of the arm mesh for visualisation + if(m_arm_mesh.size()>0 && arm_angle_changed) + { + int arm_index = 0; + for (auto it = m_arm_mesh.begin(); it != m_arm_mesh.end(); ++it) + { + auto mesh_object = renderer::get_mesh_by_id(*it); + if(arm_index == 0) + { + mesh_object->m_position = glm::vec3{SCARA_OFFSET_X, effector_pos.y, -SCARA_OFFSET_Y};; + } + else if(arm_index == 1) + { + const float a_sin = std::sin(glm::radians( arm_angle[0])) * SCARA_LINKAGE_1, + a_cos = std::cos(glm::radians(arm_angle[0])) * SCARA_LINKAGE_1; + mesh_object->m_position = glm::vec3{a_cos + SCARA_OFFSET_X, effector_pos.y, -(a_sin + SCARA_OFFSET_Y)}; + } + glm::qua m_rotation = glm::qua(glm::radians(glm::vec3(0.0f, arm_angle[arm_index], 0.0f))); + mesh_object->m_rotation = m_rotation; + mesh_object->m_transform_dirty = true; + mesh_object->m_visible = (follow_mode != FOLLOW_Z)&&scara_arm->enabled; + arm_index++; + } + } +#endif if (draw_list_update) { renderer::render_mesh(m_bed_mesh); for (auto mesh : m_extruder_mesh) { renderer::render_mesh(mesh); } +#if ENABLED(MP_SCARA) + for (auto mesh : m_arm_mesh) { + renderer::render_mesh(mesh); + } +#endif for (auto& ext : extrusion) { renderer::render_mesh(ext.mesh); } diff --git a/src/MarlinSimulator/visualisation.h b/src/MarlinSimulator/visualisation.h index 7c2ce09..35cc184 100644 --- a/src/MarlinSimulator/visualisation.h +++ b/src/MarlinSimulator/visualisation.h @@ -5,6 +5,7 @@ #include "hardware/print_bed.h" #include "hardware/bed_probe.h" +#include "hardware/ScaraArm.h" #include "hardware/KinematicSystem.h" #include @@ -137,11 +138,15 @@ class Visualisation { void ui_info_callback(UiWindow*); std::vector extrusion {}; +#if ENABLED(MP_SCARA) + std::vector arm_angle {}; + bool arm_angle_changed = false; +#endif std::mutex extrusion_mutex {}; void set_head_position(size_t hotend_index, extruder_state& position); bool points_are_collinear(const glm::vec3 a, const glm::vec3 b, const glm::vec3 c, double const threshold) const; - + renderer::mesh_id_t scara_add_mesh_arm(const double link_length); FollowMode follow_mode = FOLLOW_NONE; bool render_full_path = true; bool render_path_line = false; @@ -154,6 +159,9 @@ class Visualisation { PerspectiveCamera camera; opengl_util::FrameBuffer* framebuffer = nullptr; std::vector m_extruder_mesh; +#if ENABLED(MP_SCARA) + std::vector m_arm_mesh; +#endif renderer::mesh_id_t m_bed_mesh; std::shared_ptr extrusion_program;