日経平均株価」タグアーカイブ

Pythonを使ってヤフーファイナンス日経平均株価の時系列を取得、スクレイピング

Python を使ってヤフーファイナンス 日経平均株価の時系列を取得、スクレイピング
#https://stocks.finance.yahoo.co.jp/stocks/history/?code=998407.O
#日経平均株価の時系列のテーブル表から該当の文字列を取得する、日付 始値 高値 安値 終値

https://github.com/maseda1030/yahoofinance_python.git

import time
from selenium import webdriver
import csv
import datetime
import os

class jikeiretsu:
    def __init__(self,day,kopen,khigh,klow,kclose):
        self.day=day
        self.kopen=kopen
        self.khigh=khigh
        self.klow=klow
        self.kclose=kclose
        
class yahooFinanceTimeline:
    def __init__(self):
        self.hello="yahoo Finace"
        
    def getTimeline(self):
        #print("カプセルにして取得")
         #動作確認のためのメソッド
        # 仮想ブラウザ起動、URL先のサイトにアクセス
        driver = webdriver.Chrome('/usr/local/bin/chromedriver')#ここでエラーになったらパスが違うかchromedriverをインストールする
        #他のエラーで、「unexpectedly exited. Status code was:-9」だったら、Macの場合はシステム環境設定 → セキュリティとプライバシー で許可すればよい
        url='https://stocks.finance.yahoo.co.jp/stocks/history/?code=998407.O'
        driver.get(url)
        time.sleep(1)
        #title = driver.title
        #print(title)
        main = driver.find_element_by_id("main")
        el = main.find_element_by_css_selector(".padT12.marB10.clearFix")
        tableElem = el.find_element_by_tag_name("table")
        trs = tableElem.find_elements_by_tag_name("tr")
        ths = trs[0].find_elements_by_tag_name("th")
        kabuka=""
        #thタグは1行目のTRにだけ存在する。
        for f in range(0,len(ths)):#日付	始値	高値	安値	終値
            ths[f].text
            kabuka+=ths[f].text+" "
        print(kabuka)
        jikeiretsuArray=[]
        for i in range(0,len(trs)):
            tds = trs[i].find_elements_by_tag_name("td")
            if len(tds)>=5:
                getJikeiretsu=jikeiretsu(tds[0].text,tds[1].text,tds[2].text,tds[3].text,tds[4].text)
                jikeiretsuArray.append(getJikeiretsu)
            else: 
                print("tdsの数が足りない行があるので無視")
        time.sleep(1)    
        driver.close()#起動したウィンドウを閉じる
        print("通常出力日付	始値	高値	安値	終値")
        for f in range(0,len(jikeiretsuArray)):
            print(jikeiretsuArray[f].day,jikeiretsuArray[f].kopen,jikeiretsuArray[f].khigh,jikeiretsuArray[f].klow,jikeiretsuArray[f].kclose)
        print('+----------------------+')
        print("個人的出力順、CSVカンマ区切りで 桁区切りのカンマは削除、昇順day,High,Low,Open,Close,AdjClose")#("個人的な利用の出力順、昇順day,High,Low,Open,Close,AdjClose")    
        count=len(jikeiretsuArray)
        tmpstr=""    
        for n in reversed(range(count)):#).replace(',','') カンマを削除
            tmpstr=jikeiretsuArray[n].day+","+jikeiretsuArray[n].khigh.replace(',','')+","+jikeiretsuArray[n].klow.replace(',','')+","+\
                  jikeiretsuArray[n].kopen.replace(',','')+","+jikeiretsuArray[n].kclose.replace(',','')+","+\
                  jikeiretsuArray[n].kclose.replace(',','')
            print(tmpstr)

    #テスト用のメソッドなので実際は不要なメソッド        
    def getTimelineTest(self):
        print("test")
        #動作確認のためのメソッド
        # 仮想ブラウザ起動、URL先のサイトにアクセス
        driver = webdriver.Chrome('/usr/local/bin/chromedriver')#ここでエラーになったらパスが違うかchromedriverをインストールする
        #他のエラーで、「unexpectedly exited. Status code was:-9」だったら、Macの場合はシステム環境設定 → セキュリティとプライバシー で許可すればよい
        url='https://stocks.finance.yahoo.co.jp/stocks/history/?code=998407.O'
        #driver.get(url+str(code)+'.T')
        driver.get(url)
        time.sleep(1)
        #title = driver.title
        #print(title)
        main = driver.find_element_by_id("main")
        #el = main.find_element_by_id("stockinf")
        #nextClass = el.find_element_by_css_selector(".stocksDtl.clearFix")
        el = main.find_element_by_css_selector(".padT12.marB10.clearFix")
        tableElem = el.find_element_by_tag_name("table")
        trs = tableElem.find_elements_by_tag_name("tr")
        ths = trs[0].find_elements_by_tag_name("th")
        kabuka=""
        #thタグは1行目のTRにだけ存在する。
        for f in range(0,len(ths)):#日付	始値	高値	安値	終値
            ths[f].text
            kabuka+=ths[f].text+" "
        print(kabuka)
        kabuka=""
        for i in range(0,len(trs)):
            tds = trs[i].find_elements_by_tag_name("td")
            for m in range(0,len(tds)):
                kabuka+=tds[m].text+" "#ここはカプセルにしてクラスオブジェクトを配列に入れたほうがいいかも
                #print(kabuka)
            print(kabuka)
            kabuka=""
        time.sleep(1)    
        driver.close()#起動したウィンドウを閉じる
###START
print("START#####################################")
print("Japan yahoo financeの日経平均株価の時系列")
getstock=yahooFinanceTimeline()
getstock.getTimeline()

print("End#####################################")

 

出力例

START#####################################
Japan yahoo financeの日経平均株価の時系列
カプセルにして取得
日付 始値 高値 安値 終値 
tdsの数が足りない行があるので無視
通常出力日付	始値	高値	安値	終値
2021年2月16日 30,229.46 30,714.52 30,191.65 30,467.75
2021年2月15日 29,662.41 30,092.34 29,662.41 30,084.15
2021年2月12日 29,635.88 29,650.51 29,417.32 29,520.07
2021年2月10日 29,412.55 29,562.93 29,368.18 29,562.93
2021年2月9日 29,435.61 29,585.75 29,350.48 29,505.93
2021年2月8日 28,831.58 29,400.56 28,817.6 29,388.5
2021年2月5日 28,631.46 28,785.71 28,548.27 28,779.19
2021年2月4日 28,557.46 28,600.22 28,325.89 28,341.95
2021年2月3日 28,482.71 28,669.95 28,402.3 28,646.5
2021年2月2日 28,207.48 28,379.31 28,089.12 28,362.17
2021年2月1日 27,649.07 28,107.1 27,649.07 28,091.05
2021年1月29日 28,320.72 28,320.72 27,629.8 27,663.39
2021年1月28日 28,169.27 28,360.48 27,975.85 28,197.42
2021年1月27日 28,665.34 28,754.99 28,542 28,635.21
2021年1月26日 28,696.3 28,740.71 28,527.81 28,546.18
2021年1月25日 28,698.89 28,822.29 28,566.85 28,822.29
2021年1月22日 28,580.2 28,698.18 28,527.16 28,631.45
2021年1月21日 28,710.41 28,846.15 28,677.61 28,756.86
2021年1月20日 28,798.74 28,801.19 28,402.11 28,523.26
2021年1月19日 28,405.49 28,720.91 28,373.34 28,633.46
+----------------------+
個人的出力順、カンマを削除、昇順day,High,Low,Open,Close,AdjClose
2021年1月19日,28720.91,28373.34,28405.49,28633.46,28633.46
2021年1月20日,28801.19,28402.11,28798.74,28523.26,28523.26
2021年1月21日,28846.15,28677.61,28710.41,28756.86,28756.86
2021年1月22日,28698.18,28527.16,28580.2,28631.45,28631.45
2021年1月25日,28822.29,28566.85,28698.89,28822.29,28822.29
2021年1月26日,28740.71,28527.81,28696.3,28546.18,28546.18
2021年1月27日,28754.99,28542,28665.34,28635.21,28635.21
2021年1月28日,28360.48,27975.85,28169.27,28197.42,28197.42
2021年1月29日,28320.72,27629.8,28320.72,27663.39,27663.39
2021年2月1日,28107.1,27649.07,27649.07,28091.05,28091.05
2021年2月2日,28379.31,28089.12,28207.48,28362.17,28362.17
2021年2月3日,28669.95,28402.3,28482.71,28646.5,28646.5
2021年2月4日,28600.22,28325.89,28557.46,28341.95,28341.95
2021年2月5日,28785.71,28548.27,28631.46,28779.19,28779.19
2021年2月8日,29400.56,28817.6,28831.58,29388.5,29388.5
2021年2月9日,29585.75,29350.48,29435.61,29505.93,29505.93
2021年2月10日,29562.93,29368.18,29412.55,29562.93,29562.93
2021年2月12日,29650.51,29417.32,29635.88,29520.07,29520.07
2021年2月15日,30092.34,29662.41,29662.41,30084.15,30084.15
2021年2月16日,30714.52,30191.65,30229.46,30467.75,30467.75
End#####################################

 

Blender2.91、Pythonで日経平均株価のローソク足を3Dにしてみた

内容

2020年12月〜2021年1月のある期間の日経平均株価チャートを自動作成
約1、2週間分程度の株価

3Dローソク足(株に興味のない人はつまらないかも、、、)
BlenderのPythonを使うとこんなこともできるということを実践しただけの紹介動画

>>作成したローソク足の3D オブジェクトの紹介、BlenderのPython実行

ユーチューブ動画

参考サイト

https://qiita.com/kjunichi/items/a36fdc9db3876e068249
https://qiita.com/hibit/items/1ac97c71d5adc5b45f85

ブログに記載したインストール内容はこちら
https://pikucha.sakura.ne.jp/blog/2020/12/27/mac%e7%89%88blender%e3%81%aepython%e3%81%abpip%e3%80%81pandas_datareader%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%ab%e3%81%97%e3%81%9f%e3%83%a1%e3%83%a2/

#日経平均株価 とは
「東京証券取引所第一部に上場する約2,000銘柄の株式のうち225銘柄を対象」原則「225銘柄の株価の合計 ÷ 225」となる。修正等ある。
https://ja.m.wikipedia.org/wiki/%E6%97%A5%E7%B5%8C%E5%B9%B3%E5%9D%87%E6%A0%AA%E4%BE%A1

#ローソク足とは、
https://ja.wikipedia.org/wiki/%E3%83%AD%E3%83%BC%E3%82%BD%E3%82%AF%E8%B6%B3%E3%83%81%E3%83%A3%E3%83%BC%E3%83%88

「単位期間中に初めに付いた値段を始値(はじめね)、最後に付いた値段を終値(おわりね)、最も高い値段を高値(たかね)、最も安い値段を安値(やすね)」の値をもとにローソクの形状のように表現したもの
ローソク足は江戸時代に出羽国の本間宗久が発案

日経平均株価のデータを取得して、BlenderのPythonを使いローソク足の3D オブジェクトを作成した。

環境:MacOS BigSur

#Blender2.91
Blender用pythonモジュール: #pandas_datareader
準備:Pythonモジュールをインストールする必要がある。
Mac版BlenderのPythonにPip、pandas_datareaderインストールしておく。
・PythonはMacOS BigSur用とBlender用とが存在する。つまり保存場所が異なる。
よってBlenderで使いたいモジュールが必要なときは、個別でインストールが必要。
つまり、MacOSでpandas_datareaderをインストールしても、BlenderのPythonでは
使えない。

目的

:Blender2.91、Pythonスクリプトで日経平均株価データを米ヤフーファイナンスからネット上で取得して、ローソク足として3D(円柱)オブジェクトを作成する。
チャートデータは数日〜1週間程度のデータ

注意事項:

Pythonの文法の説明はほとんどしません。
BlenderのPythonの仕様について投稿者は、よく理解しておらず試行錯誤で作成し、推奨ではないコードの記述や間違いがあります。よって質問等があっても正しく答えられる知識がないため回答できない場合があります。
ご承知おきください。(他の人の回答を期待します。)

・Pythonスクリプトコードの概略説明

米ヤフーファイナンスから日経平均株価のデータを取得
始値、終値、高値、安値データを取得
始値より終値が大きければ陽線(赤)
小さければ陰線(青)とする
始値、終値からローソク本体の大きさ位置を決める
高値、安値からローソクのひげの大きさ位置を決める
直近の日のローソク足だけ横を向いた円錐を配置
直近のローソク足の始値終値を記載
直近の日付を記載
目盛りを配置

^読み方:キャロット

オブジェクトの原点がオブジェクトの中心に配置されていて、オブジェクトの移動やリサイズをする場合は問題は発生しないが、オブジェクトの頂点がオブジェクトの原点(中心点)より離れた位置に配置されていると、
Resizeしたときに、ポイントの縮尺が変わり、想定した位置に配置されない(バグではなく、操作や理解の問題)。
よって、リサイズして、ポイントを移動させたいときは、
オブジェクト自体を移動させてから、リサイズや個別頂点ポイントを移動させたほうが良いと思う。

 

・補足説明

Blenderターミナル起動(print出力を確認するためにターミナルが必要)
/Applications/Blender.app/Contents/MacOS/Blender

Blender2.91のpython場所 –MacOSpythonと異なる場所にある(バージョンが変わる毎にディレクトリが変わる。2.91の部分)
/Applications/Blender.app/Contents/Resources/2.91/python

 

Pythonコード

2021/01/04時点の分、Blenderで実行する。できれば、ターミナルからBlenderを起動してから、Scriptingで使用

修正履歴:2021/01/06、始値終値が重ならないように位置を調整

import os
import bpy
import math
import copy
import time
import pandas_datareader.data as data
from datetime import datetime,timedelta

#blender 2.91 
#Mac Big Sur
#ターミナル起動
#/Applications/Blender.app/Contents/MacOS/Blender

#GLOBAL
# count
# xmove
# bairitsu
#修正履歴
#2021/01/06:始値、終値の位置が重ならないように調整

#https://bluebirdofoz.hatenablog.com/entry/2018/04/25/231414
# オブジェクトの原点変更
# オブジェクトの原点を指定位置に移動する
# 引数   arg_objectname:指定オブジェクト名
# 戻り値
def set_origin_cursor(arg_objectname='Default',arg_location=(0,0,0)):
  # 他のオブジェクトの寸法を適用しないよう全てのオブジェクトを走査する
  for ob in bpy.context.scene.objects:
    # 非選択状態に設定する
    #ob.select=False#2.7
    ob.select_set(False) #2.9
  # 指定オブジェクトを取得する
  selectob = bpy.data.objects[arg_objectname]
  # 変更オブジェクトをアクティブに変更する
  #bpy.context.scene.objects.active = selectob#2.7
  bpy.context.view_layer.objects.active=selectob#2.9
  # 変更オブジェクトを選択状態にする  
  #selectob.select=True #2.7
  selectob.select_set(True) #2.9
  # 3Dカーソルの元の位置を記録しておく(参照型のコピー)
  #cursorpos = copy.copy(bpy.context.scene.cursor_location)
  # 3Dカーソルの位置を指定位置に移動する
  #bpy.context.scene.cursor_location = arg_location#2.7
  bpy.context.scene.cursor.location=arg_location#2.9
  # オブジェクトの原点を3Dカーソル位置に移動する
  bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
  # 3Dカーソルの位置を元に戻す
  #bpy.context.scene.cursor_location = cursorpos #2.7
  #bpy.context.scene.cursor.location=cursorpos#2.9 not use
  bpy.context.scene.cursor.location=(0.0,0.0,0.0)
  return

def fcandle(candleType,kopen,kclose,bairitsu,xmove,mat1,mat2):
    #count is Global
    global count
    #global xmove
    #global bairitsu
    
    if bairitsu=='' or bairitsu==0:
        print('def fcandle(),bairitsu not defined,use 0.001')
        bairitsu=0.001
    if count=='':
        print('def fcandle(),count is Global, not defined, Please check, so use 1')
        count=1
                  
    candle=candleType
    #1.円柱location:図形の中心座標 radius:円の半径 depth:高さ rotation:立体の回転角(rad)
    bpy.ops.mesh.primitive_cylinder_add(location=(0, 0, 0), radius=0.022, depth=3, rotation=(0, 0, 0))
    if candle=='yousen':
        bpy.context.object.data.materials.append(mat1) # 材質(赤)指定
    else:#insen 
        bpy.context.object.data.materials.append(mat2) # 材質(青)指定
    bpy.ops.transform.translate(value=(xmove,0,0))
    #location=bpy.context.object.location
    
    for obj in bpy.context.selected_objects:
        if obj.name=='Cylinder':
            tmpcount=count+1
            obj.name = "candle"+str(tmpcount)
    
    #bpy.ops.object.shade_smooth()
    
    new_bar = bpy.context.object
    for vert in new_bar.data.vertices:
        if candle=='yousen':
            if vert.co[2] > 0:#Zjiku ni up
                vert.co[2] = kclose*bairitsu#close
            else:
                vert.co[2] = kopen*bairitsu
        elif candle=='insen':
            if vert.co[2] > 0:
                vert.co[2] = kopen*bairitsu
            else:
                vert.co[2] = kclose*bairitsu
    clocation=(xmove,0,(kopen+kclose)*bairitsu/2) 
    set_origin_cursor(obj.name,clocation)
    location=bpy.context.object.location
    
    return  location#candle             
#end def

def fcandle_hige(candleType,khigh,klow,bairitsu,candleLocation,mat1,mat2):
    global count
    #global xmove
    #global bairitsu    
    #count,bairitsu is Global
    #if bairistu=='' or bairitsu==0:
    #    print('def fcandle_hige(),bairitsu not defined, so use 0.001')
    #    bairitsu=0.001
    if count=='':
        print('def fcandle_hige(),count is Global, not defined, Please check, so use 1')
        count=1
        
    candle=candleType
    bpy.ops.mesh.primitive_cylinder_add(location=(0, 0, 0), radius=0.022/7, depth=3, rotation=(0, 0, 0))
    if candle=='yousen':
        bpy.context.object.data.materials.append(mat1) # 材質(赤)指定
    else:#insen 
        bpy.context.object.data.materials.append(mat2) # 材質(青)指定
    bpy.ops.transform.translate(value=(candleLocation[0],candleLocation[1],0))#hige location is same candle location
    
    for obj in bpy.context.selected_objects:
        if obj.name=='Cylinder':
            tmpcount=count+1
            obj.name = "hige"+str(tmpcount)
    
    #xmove+=0.048
    #bpy.ops.object.shade_smooth()
    
    new_bar = bpy.context.object
    for vert in new_bar.data.vertices:
            if vert.co[2] > 0:#Zjiku ni up
                vert.co[2] = khigh*bairitsu#close
            else:
                vert.co[2] = klow*bairitsu
    set_origin_cursor(obj.name,candleLocation)
    
#end def
# テキストオブジェクトの追加
def add_text(text, t_color,location):
# 角度設定時に利用
  ROT_QUATER = math.pi / 2
  bpy.ops.object.text_add()
  ob = bpy.context.object
  ob.data.body = text
  ob.data.extrude = 0.05
  ob.data.bevel_depth = 0.002
  
  bpy.ops.font.open(filepath="/System/Library/Fonts/ヒラギノ角ゴシック W6.ttc")
  bpy.data.fonts["HiraginoSans-W6"].name = "HiraginoSans-W6"
  fnt = bpy.data.fonts.load('/System/Library/Fonts/ヒラギノ角ゴシック W6.ttc')
  ob.data.font = fnt 
  
  ob.rotation_euler[0] = ROT_QUATER
  # 3Dカーソルの位置を0,0,0
  bpy.context.scene.cursor.location=(0.0,0.0,0.0)
  #3Dカーソルを原点を変更してから、translateする必要がある。
  bpy.ops.transform.translate(value=location)#26500*0.001,(1.8,0.1/3,26.5)
  bpy.ops.transform.resize(value=(0.2,0.1,0.2)) # 図形を変形
  
  #ob.rotation_euler[2] = ROT_QUATER
  ob.data.align_x = 'CENTER'
  ob.data.align_y = 'CENTER'
  mat = bpy.data.materials.new('color_txt')
  mat.diffuse_color = t_color#(0.8, 0.8, 0.8, 1.0)
  # マテリアルスロットを追加する
  bpy.ops.object.material_slot_add()
  # 作成したマテリアルスロットに新規マテリアルを設定する
  bpy.context.object.active_material = mat
  #ob.active_material.diffuse_color = (1,0,0)
  #bpy.context.object.active_material.diffuse_color = (1,0,0)
  #mat.diffuse_color = (1.0,0.0,0.0)
  
  #mat.diffuse_color = (1,0,0)#t_color #error , I do not yet 2020/05/15 
  #ob.data.materials.append(mat)
  #ob.active_material.diffuse_color = t_color # error

#convert to mesh

  #s = bpy.context.scene.objects.active
  #s.name = "text_name"
  bpy.ops.object.convert(target='MESH')# work
  for obj in bpy.context.selected_objects:
     if obj.name=='Text':
         obj.name=text

  return ob
#end def

def add_textKai(text, t_color,location,size):
# 角度設定時に利用
  ROT_QUATER = math.pi / 2
  bpy.ops.object.text_add()
  ob = bpy.context.object
  ob.data.body = text
  ob.data.extrude = 0.05
  ob.data.bevel_depth = 0.002
  
  bpy.ops.font.open(filepath="/System/Library/Fonts/ヒラギノ角ゴシック W6.ttc")
  bpy.data.fonts["HiraginoSans-W6"].name = "HiraginoSans-W6"
  fnt = bpy.data.fonts.load('/System/Library/Fonts/ヒラギノ角ゴシック W6.ttc')
  ob.data.font = fnt 
  
  ob.rotation_euler[0] = ROT_QUATER
  # 3Dカーソルの位置を0,0,0
  bpy.context.scene.cursor.location=(0.0,0.0,0.0)
  #3Dカーソルを原点を変更してから、translateする必要がある。
  bpy.ops.transform.translate(value=location)#26500*0.001,(1.8,0.1/3,26.5)
  bpy.ops.transform.resize(value=size) # 図形を変形(0.2,0.1,0.2)
  
  #ob.rotation_euler[2] = ROT_QUATER
  ob.data.align_x = 'CENTER'
  ob.data.align_y = 'CENTER'
  mat = bpy.data.materials.new('color_txt')
  mat.diffuse_color = t_color#(0.8, 0.8, 0.8, 1.0)
  # マテリアルスロットを追加する
  bpy.ops.object.material_slot_add()
  # 作成したマテリアルスロットに新規マテリアルを設定する
  bpy.context.object.active_material = mat
  #ob.active_material.diffuse_color = (1,0,0)
  #bpy.context.object.active_material.diffuse_color = (1,0,0)
  #mat.diffuse_color = (1.0,0.0,0.0)
  #mat.diffuse_color = (1,0,0)#t_color #error , I do not yet 2020/05/15 
  #ob.data.materials.append(mat)
  #ob.active_material.diffuse_color = t_color # error
#convert to mesh
  #s = bpy.context.scene.objects.active
  #s.name = "text_name"
  bpy.ops.object.convert(target='MESH')# work
  for obj in bpy.context.selected_objects:
     if obj.name=='Text':
         obj.name=text  
  return ob
#end def

#2020/12/29
#print('Max:',max(df['High']))#最大値が取れる
#高値の最大値maxと安値の最小値minを取得して
#500円ごとのバー基準株価線(26500,27000,27500)を自動で作成したい。
def makeBarMaxtoMin(highobj,lowobj):
    #print('Max:',max(highobj))#df['High']
    #print('Min:',min(lowobj))#df['Low']
    #bairitsu is Global
    global count
    global xmove
    global bairitsu    
    #if bairistu=='' or bairitsu==0:
    #    print('def makeBarMaxtoMin(),bairitsu not defined,use 0.001')
     #   bairitsu=0.001    
    #every 500yen
    priceRange=500
    #highPriceNumはバーの本数を取得する
    highPriceNum,highmod=divmod(max(highobj),priceRange)#26200/priceRange
    lowPriceNum,lowmod=divmod(min(lowobj),priceRange)
    #高値については、余りが出たら、1を追加する
    #print('highmod:',highmod)
    if highmod!=0:
        highPriceNum=highPriceNum+1
        #Rangeで範囲を指定してしようする場合1加算では足りないので、rangeで更に1を加算する
        #print('after highPriceNum:',highPriceNum)

    for i in range(math.floor(lowPriceNum),math.floor(highPriceNum+1)):
        #range()が出力するのは、(highPriceNum-1)なので1を加算してhighPriceNum分までを計算させる
        print('barPrice:',i*priceRange)
        #i*priceRangeの位置でBarオブジェクトを作成する。
        # 3Dカーソルの位置を0,0,0
        bpy.context.scene.cursor.location=(0.0,0.0,0.0) 
        color=(0.8,0.5,0.8,0.8)
        add_text(str(i*priceRange), color,(1.8,0.1/3, (i*priceRange)*bairitsu+0.045))#0.045 is ajustment
        
        bpy.context.scene.cursor.location=(0.0,0.0,0.0)
        # 平板作成 26500bar1
        bpy.ops.mesh.primitive_cube_add(location=(0, 0, 0), size=2.0)
        bpy.ops.transform.translate(value=(0.0,0.1/2,(i*priceRange)*bairitsu))#26500*0.001
        bpy.ops.transform.resize(value=(2.0,0.06/6,0.01/6)) # 図形を変形
        bpy.context.object.data.materials.append(mat3) # 材質
        for obj in bpy.context.selected_objects:
            if obj.name=='Cube':
                obj.name='bar_'+str(i*priceRange) 
#end def
######################################################################
#main
######################################################################
count=0#count is Global
xmove=0.8#1# move distancs
bairitsu=0.001# size Global

#Stock date
n=maenohi=5
end = datetime.now()
#start = end - timedelta(days=maenohi)#end.day-7 changes
#start = datetime(end.year, end.month, end.day-7)
##土日があると表示させるローソク足の数が少ないので、数が満たされるまでループするためSleepを入れた
#大量のデータはCSVで取得してからローソク足にしたほうが良さそう
x=0
while x<=(maenohi):
    start = end - timedelta(days=n)
    df=data.DataReader('^N225','yahoo',start,end)#3990.T,#^N225
    date=df.index# 日付
    time.sleep(3)
    print('len(date):',len(date))
    print('3秒待ち')
    x=len(date)
    n=n+1
print(df.head(5))
if len(date)==0:
    print('ERROR Can not get any Price data, Check internet or yahoo finance com.')
    sys.exit()

# 既存要素削除
for item in bpy.data.meshes:
    bpy.data.meshes.remove(item)

for item in bpy.data.materials:
    bpy.data.materials.remove(item)
        
#bpy.ops.outliner.item_rename()
#2.立方体 location:図形の中心座標 size:立方体の一辺の長さ rotation:立体の回転角(rad)
#bpy.ops.mesh.primitive_cube_add(location=(0, 0, 0), size=1.0, rotation=(0, 0, 0))

# 2.材質の定義(赤色)
mat1 = bpy.data.materials.new('Red')
mat1.diffuse_color = (1.0, 0.0, 0.0, 1.0)

# 3.材質の定義(青色)
mat2 = bpy.data.materials.new('blue')
mat2.diffuse_color = (0.0, 0.0, 1.0, 1.0)

mat3 = bpy.data.materials.new('gray')
mat3.diffuse_color = (0.8, 0.8, 0.8, 0.5)

mat5 = bpy.data.materials.new('yellow')
mat5.diffuse_color = (1.0, 0.9, 0.1, 1.0)

# 平板作成 27000bar
#bpy.ops.mesh.primitive_cube_add(location=(0, 0, 0), size=2.0)
#Resizeして、ポイント移動をするとポイントの縮尺が変わり、想定した位置に移動しない(推測)。
#これはオブジェクトの原点とScaleの考え方の違いかもしれない。
#よって、リサイズして、ポイントを移動させたいときは、
#リサイズをする前にオブジェクト自体を移動させてから、ポイントを移動させたほうが良いと思う。
#bpy.ops.transform.translate(value=(0.0,0.1/2,27))#27000*0.001
#bpy.ops.transform.resize(value=(2.0,0.06/6,0.01/6)) # 図形を変形
#bpy.context.object.data.materials.append(mat3) # 材質

# 平板作成 26500bar1
#bpy.ops.mesh.primitive_cube_add(location=(0, 0, 0), size=2.0)
#bpy.ops.transform.translate(value=(0.0,0.1/2,bar1*bairitsu))#26500*0.001
#bpy.ops.transform.resize(value=(2.0,0.06/6,0.01/6)) # 図形を変形
#bpy.context.object.data.materials.append(mat3) # 材質

# 3Dカーソルの位置を0,0,0
#bpy.context.scene.cursor_location =(0.0,0.0,0.0)
bpy.context.scene.cursor.location=(0.0,0.0,0.0)

#26500txt
#color=(0.8,0.5,0.8,0.8)
#add_text('26500', color,(1.8,0.1/3,bar1*bairitsu+0.045))#0.045 is ajustment
#27000txt
#add_text('27000', color,(1.8,0.1/3,bar2*bairitsu+0.045))


#date=df.indexをカウントして、それぞれを取得する。ちょっとスマートではないが、、
for fdate in date:
    khigh=df['High'][count]
    klow=df['Low'][count]
    kopen=df['Open'][count]
    kclose=df['Adj Close'][count]
    #ここに日付ごとの処理を入れる。
    #
    if kopen-kclose<0:
        candle='yousen'#color Red
        #print('陽線')
    else:
        candle='insen'#color Blue
        #print('陰線')
    #objを生成する。
    #始値、終値でZ軸の高さを設定する。
    print( fdate.strftime("%Y/%m/%d") )#2020-12-22 00:00:00となるので、時刻を除く2020-12-22
    #Candle_Main####################################################
    candleLocation=fcandle(candle,kopen,kclose,bairitsu,xmove,mat1,mat2)
    xmove+=0.048
    
    #Candle_hige####################################################
    fcandle_hige(candle,khigh,klow,bairitsu,candleLocation,mat1,mat2)
    #count is Global      
    count+=1

#最後のローソクのobjの横に矢印を与える
#この場合、ローソクの原点を移動させて、ローソクの中心に移動させる必要がある
candleCount=0
for obj in bpy.data.objects:
    if 'candle' in obj.name:
        #print(obj.name)
        candleCount+=1
candleName='candle'+str(candleCount)

#Arrow
bpy.ops.mesh.primitive_cone_add(radius1=1, radius2=0, depth=2, enter_editmode=False, align='WORLD', location=(0, 0, 0), scale=(0.05, 0.05, 0.05))
#図形を回転(Y軸周りに90°)
bpy.ops.transform.rotate(value=-3.1415/2 ,orient_axis='Y')
bpy.context.object.data.materials.append(mat5) 
bpy.ops.transform.translate(value=(bpy.data.objects[candleName].location[0]+0.08,bpy.data.objects[candleName].location[1],bpy.data.objects[candleName].location[2]))#


bpy.context.scene.cursor.location=(0.0,0.0,0.0)
#open,close
color=(1.0,1.0,1.0,1.0)
#str,color,location,size
lastOpen=df['Open'][len(date)-1]#始値
lastClose=df['Close'][len(date)-1]#終値
roundOpen='O:'+str(round(lastOpen,2))#画面に表示させる直近の始値文字
roundClose='C:'+str(round(lastClose,2))#画面に表示させる直近の終値文字

add_textKai(roundOpen, color,(xmove+0.1,0,lastOpen*bairitsu),(0.06,0.05,0.06))
add_textKai(roundClose, color,(xmove+0.1,0,lastClose*bairitsu),(0.06,0.05,0.06))

#end.strftime("%Y/%m/%d") or date[len(date)-1].strftime("%Y/%m/%d")today
color=(0.0,1.0,0.0,1.0)
coneLocation=bpy.data.objects['Cone'].location
tyokkinDay=date[len(date)-1].strftime("%Y/%m/%d")
if len(date)>0:
    add_textKai(tyokkinDay,color, (coneLocation[0]+0.16,coneLocation[1],coneLocation[2]),(0.06,0.05,0.06))
#print('last day:',date[len(date)-1])

#始値、終値、直近の日付の調整。オブジェクトが重なってしまう金額が近いときに離す処理
if candle=='yousen':#Openが下側でCloseが上側にあるはず
    #bpy.data.objects[roundOpen].dimensions[1]#Z方向の幅サイズではなくてY軸、理由はローカルで回転させたから
    #bpy.data.objects[roundClose].dimensions[1]
    #bpy.data.objects[tyokkinDay].dimensions[1]
    #始値、終値、直近の日付のlocationを取得する。Z方向ではなくてY軸の幅の半分を上下に加減算して重なりを調べる
    #bpy.data.objects[roundOpen].location[2]
    #bpy.data.objects[roundClose].location[2]
    #bpy.data.objects[tyokkinDay].location[2]
    #roundCloseを調整する.roundCloseの下側位置が、直近日付の上側位置以下になっているときに、直近日付の上の方にroundCloseを上へ移動させる
    
    #location is [2]:Z, dimensions is [1]:Y
    if bpy.data.objects[roundClose].location[2]-bpy.data.objects[roundClose].dimensions[1]/2 <= bpy.data.objects[tyokkinDay].location[2]+bpy.data.objects[tyokkinDay].dimensions[1]/2:
        #直近日付の位置に、プラスへ移動
        bpy.data.objects[roundClose].location[2]=bpy.data.objects[tyokkinDay].location[2]+bpy.data.objects[tyokkinDay].dimensions[1]*1.5
    #roundOpenを調整する。roundOpenの「上側」位置が、直近日付の「下側」以上になっているときに、直近日付の「下の方」にroundOpenを下へ移動させる
    if bpy.data.objects[roundOpen].location[2]+bpy.data.objects[roundOpen].dimensions[1]/2 >=bpy.data.objects[tyokkinDay].location[2]-bpy.data.objects[tyokkinDay].dimensions[1]/2:
            #「マイナス」へ移動
        bpy.data.objects[roundOpen].location[2]=bpy.data.objects[tyokkinDay].location[1]-bpy.data.objects[tyokkinDay].dimensions[1]*1.5
else:#insen Openが上側でCloseが下側にあるはず.Yousenとは逆
    #roundOpen
    print('insen')
    if bpy.data.objects[roundOpen].location[2]-bpy.data.objects[roundOpen].dimensions[1]/2<=bpy.data.objects[tyokkinDay].location[2]+bpy.data.objects[tyokkinDay].dimensions[1]/2:
        bpy.data.objects[roundOpen].location[2]=bpy.data.objects[tyokkinDay].location[2]+bpy.data.objects[tyokkinDay].dimensions[1]*1.5
        print('Open')
    #roundClose
    if bpy.data.objects[roundClose].location[2]+bpy.data.objects[roundClose].dimensions[1]/2>=bpy.data.objects[tyokkinDay].location[2]-bpy.data.objects[tyokkinDay].dimensions[1]/2:
        bpy.data.objects[roundClose].location[2]=bpy.data.objects[tyokkinDay].location[2]-bpy.data.objects[tyokkinDay].dimensions[1]*1.5
        print('Close')

    

#2020/12/29
#print('Max:',max(df['High']))#最大値が取れる
#高値の最大値maxと安値の最小値minを取得して
#500円ごとのバー基準株価線(26500,27000,27500)を自動で作成したい。
makeBarMaxtoMin(df['High'],df['Low'])

#camera move, near Cone obj
camera_obj = bpy.data.objects['Camera']
print(camera_obj.location)
camera_obj.location=(coneLocation[0]+0.16,coneLocation[1]-3.0,coneLocation[2])

print('done.')

''' Result



'''

 

別コード、株価を記載したCSVファイルを読み込んで立体ローソク足にした

米ヤフーファイナンスに接続して当日にデータを取得すると、前日データが欠落するし、データが公開されるまで時間がかかる(20分)ので
CSVで当日データを記載したファイルを読み込んだほうが早いと思ってCSV読み取りでローソク足を立体化するPythonコードを書いた。日経平均株価データのクラスオブジェクト、カプセルデータとして扱う。CSVの場合は、数字が文字列扱いになるので、floatにするなどの型変換が必要だった。
なお、このコードには、別ファイルのBlendファイルからオブジェクト(猫)を読み込むコードを記載してある。
ファイルパスはフルパス。

import os
import bpy
import math
import copy
import time
import pandas_datareader.data as data
from datetime import datetime,timedelta

#blender 2.91 
#Mac Big Sur
#ターミナル起動
#/Applications/Blender.app/Contents/MacOS/Blender

#GLOBAL
# count
# xmove
# bairitsu

#日経平均株価データのクラスオブジェクト、カプセルデータ
class nikkeiClass:
    def __init__(self, cindex, chigh,clow,copen,cclose,cadjclose):
        self.index = cindex
        self.high = chigh
        self.low = clow
        self.open = copen
        self.close = cclose
        self.adjclose = cadjclose

#https://bluebirdofoz.hatenablog.com/entry/2018/04/25/231414
# オブジェクトの原点変更
# オブジェクトの原点を指定位置に移動する
# 引数   arg_objectname:指定オブジェクト名
# 戻り値
def set_origin_cursor(arg_objectname='Default',arg_location=(0,0,0)):
  # 他のオブジェクトの寸法を適用しないよう全てのオブジェクトを走査する
  for ob in bpy.context.scene.objects:
    # 非選択状態に設定する
    #ob.select=False#2.7
    ob.select_set(False) #2.9
  # 指定オブジェクトを取得する
  selectob = bpy.data.objects[arg_objectname]
  # 変更オブジェクトをアクティブに変更する
  #bpy.context.scene.objects.active = selectob#2.7
  bpy.context.view_layer.objects.active=selectob#2.9
  # 変更オブジェクトを選択状態にする  
  #selectob.select=True #2.7
  selectob.select_set(True) #2.9
  # 3Dカーソルの元の位置を記録しておく(参照型のコピー)
  #cursorpos = copy.copy(bpy.context.scene.cursor_location)
  # 3Dカーソルの位置を指定位置に移動する
  #bpy.context.scene.cursor_location = arg_location#2.7
  bpy.context.scene.cursor.location=arg_location#2.9
  # オブジェクトの原点を3Dカーソル位置に移動する
  bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
  # 3Dカーソルの位置を元に戻す
  #bpy.context.scene.cursor_location = cursorpos #2.7
  #bpy.context.scene.cursor.location=cursorpos#2.9 not use
  bpy.context.scene.cursor.location=(0.0,0.0,0.0)
  return

def fcandle(candleType,kopen,kclose,bairitsu,xmove,mat1,mat2):
    #count is Global
    global count
    #global xmove
    #global bairitsu
    
    if bairitsu=='' or bairitsu==0:
        print('def fcandle(),bairitsu not defined,use 0.001')
        bairitsu=0.001
    if count=='':
        print('def fcandle(),count is Global, not defined, Please check, so use 1')
        count=1
                  
    candle=candleType
    #1.円柱location:図形の中心座標 radius:円の半径 depth:高さ rotation:立体の回転角(rad)
    bpy.ops.mesh.primitive_cylinder_add(location=(0, 0, 0), radius=0.022, depth=3, rotation=(0, 0, 0))
    if candle=='yousen':
        bpy.context.object.data.materials.append(mat1) # 材質(赤)指定
    else:#insen 
        bpy.context.object.data.materials.append(mat2) # 材質(青)指定
    bpy.ops.transform.translate(value=(xmove,0,0))
    #location=bpy.context.object.location
    
    for obj in bpy.context.selected_objects:
        if obj.name=='Cylinder':
            tmpcount=count+1
            obj.name = "candle"+str(tmpcount)
    
    #bpy.ops.object.shade_smooth()
    
    new_bar = bpy.context.object
    for vert in new_bar.data.vertices:
        if candle=='yousen':
            if vert.co[2] > 0:#Zjiku ni up
                vert.co[2] = kclose*bairitsu#close
            else:
                vert.co[2] = kopen*bairitsu
        elif candle=='insen':
            if vert.co[2] > 0:
                vert.co[2] = kopen*bairitsu
            else:
                vert.co[2] = kclose*bairitsu
    clocation=(xmove,0,(kopen+kclose)*bairitsu/2) 
    set_origin_cursor(obj.name,clocation)
    location=bpy.context.object.location
    
    return  location#candle             
#end def

def fcandle_hige(candleType,khigh,klow,bairitsu,candleLocation,mat1,mat2):
    global count
    #global xmove
    #global bairitsu    
    #count,bairitsu is Global
    #if bairistu=='' or bairitsu==0:
    #    print('def fcandle_hige(),bairitsu not defined, so use 0.001')
    #    bairitsu=0.001
    if count=='':
        print('def fcandle_hige(),count is Global, not defined, Please check, so use 1')
        count=1
        
    candle=candleType
    bpy.ops.mesh.primitive_cylinder_add(location=(0, 0, 0), radius=0.022/7, depth=3, rotation=(0, 0, 0))
    if candle=='yousen':
        bpy.context.object.data.materials.append(mat1) # 材質(赤)指定
    else:#insen 
        bpy.context.object.data.materials.append(mat2) # 材質(青)指定
    bpy.ops.transform.translate(value=(candleLocation[0],candleLocation[1],0))#hige location is same candle location
    
    for obj in bpy.context.selected_objects:
        if obj.name=='Cylinder':
            tmpcount=count+1
            obj.name = "hige"+str(tmpcount)
    
    #xmove+=0.048
    #bpy.ops.object.shade_smooth()
    
    new_bar = bpy.context.object
    for vert in new_bar.data.vertices:
            if vert.co[2] > 0:#Zjiku ni up
                vert.co[2] = khigh*bairitsu#close
            else:
                vert.co[2] = klow*bairitsu
    set_origin_cursor(obj.name,candleLocation)
    
#end def
# テキストオブジェクトの追加
def add_text(text, t_color,location):
# 角度設定時に利用
  ROT_QUATER = math.pi / 2
  bpy.ops.object.text_add()
  ob = bpy.context.object
  ob.data.body = text
  ob.data.extrude = 0.05
  ob.data.bevel_depth = 0.002
  
  bpy.ops.font.open(filepath="/System/Library/Fonts/ヒラギノ角ゴシック W6.ttc")
  bpy.data.fonts["HiraginoSans-W6"].name = "HiraginoSans-W6"
  fnt = bpy.data.fonts.load('/System/Library/Fonts/ヒラギノ角ゴシック W6.ttc')
  ob.data.font = fnt 
  
  ob.rotation_euler[0] = ROT_QUATER
  # 3Dカーソルの位置を0,0,0
  bpy.context.scene.cursor.location=(0.0,0.0,0.0)
  #3Dカーソルを原点を変更してから、translateする必要がある。
  bpy.ops.transform.translate(value=location)#26500*0.001,(1.8,0.1/3,26.5)
  bpy.ops.transform.resize(value=(0.2,0.1,0.2)) # 図形を変形
  
  #ob.rotation_euler[2] = ROT_QUATER
  ob.data.align_x = 'CENTER'
  ob.data.align_y = 'CENTER'
  mat = bpy.data.materials.new('color_txt')
  mat.diffuse_color = t_color#(0.8, 0.8, 0.8, 1.0)
  # マテリアルスロットを追加する
  bpy.ops.object.material_slot_add()
  # 作成したマテリアルスロットに新規マテリアルを設定する
  bpy.context.object.active_material = mat
  #ob.active_material.diffuse_color = (1,0,0)
  #bpy.context.object.active_material.diffuse_color = (1,0,0)
  #mat.diffuse_color = (1.0,0.0,0.0)
  
  #mat.diffuse_color = (1,0,0)#t_color #error , I do not yet 2020/05/15 
  #ob.data.materials.append(mat)
  #ob.active_material.diffuse_color = t_color # error

#convert to mesh

  #s = bpy.context.scene.objects.active
  #s.name = "text_name"
  bpy.ops.object.convert(target='MESH')# work
  for obj in bpy.context.selected_objects:
     if obj.name=='Text':
         obj.name=text

  return ob
#end def

def add_textKai(text, t_color,location,size):
# 角度設定時に利用
  ROT_QUATER = math.pi / 2
  bpy.ops.object.text_add()
  ob = bpy.context.object
  ob.data.body = text
  ob.data.extrude = 0.05
  ob.data.bevel_depth = 0.002
  
  bpy.ops.font.open(filepath="/System/Library/Fonts/ヒラギノ角ゴシック W6.ttc")
  bpy.data.fonts["HiraginoSans-W6"].name = "HiraginoSans-W6"
  fnt = bpy.data.fonts.load('/System/Library/Fonts/ヒラギノ角ゴシック W6.ttc')
  ob.data.font = fnt 
  
  ob.rotation_euler[0] = ROT_QUATER
  # 3Dカーソルの位置を0,0,0
  bpy.context.scene.cursor.location=(0.0,0.0,0.0)
  #3Dカーソルを原点を変更してから、translateする必要がある。
  bpy.ops.transform.translate(value=location)#26500*0.001,(1.8,0.1/3,26.5)
  bpy.ops.transform.resize(value=size) # 図形を変形(0.2,0.1,0.2)
  
  #ob.rotation_euler[2] = ROT_QUATER
  ob.data.align_x = 'CENTER'
  ob.data.align_y = 'CENTER'
  mat = bpy.data.materials.new('color_txt')
  mat.diffuse_color = t_color#(0.8, 0.8, 0.8, 1.0)
  # マテリアルスロットを追加する
  bpy.ops.object.material_slot_add()
  # 作成したマテリアルスロットに新規マテリアルを設定する
  bpy.context.object.active_material = mat
  #ob.active_material.diffuse_color = (1,0,0)
  #bpy.context.object.active_material.diffuse_color = (1,0,0)
  #mat.diffuse_color = (1.0,0.0,0.0)
  #mat.diffuse_color = (1,0,0)#t_color #error , I do not yet 2020/05/15 
  #ob.data.materials.append(mat)
  #ob.active_material.diffuse_color = t_color # error
#convert to mesh
  #s = bpy.context.scene.objects.active
  #s.name = "text_name"
  bpy.ops.object.convert(target='MESH')# work
  for obj in bpy.context.selected_objects:
     if obj.name=='Text':
         obj.name=text  
  return ob
#end def

#2020/12/29
#print('Max:',max(df['High']))#最大値が取れる
#高値の最大値maxと安値の最小値minを取得して
#500円ごとのバー基準株価線(26500,27000,27500)を自動で作成したい。
def makeBarMaxtoMin(highobj,lowobj):
    #print('Max:',max(highobj))#df['High']
    #print('Min:',min(lowobj))#df['Low']
    #bairitsu is Global
    global count
    global xmove
    global bairitsu    
    #if bairistu=='' or bairitsu==0:
    #    print('def makeBarMaxtoMin(),bairitsu not defined,use 0.001')
     #   bairitsu=0.001    
    #every 500yen
    priceRange=500
    #highPriceNumはバーの本数を取得する
    highPriceNum,highmod=divmod(max(highobj),priceRange)#26200/priceRange
    lowPriceNum,lowmod=divmod(min(lowobj),priceRange)
    #高値については、余りが出たら、1を追加する
    #print('highmod:',highmod)
    if highmod!=0:
        highPriceNum=highPriceNum+1
        #Rangeで範囲を指定してしようする場合1加算では足りないので、rangeで更に1を加算する
        #print('after highPriceNum:',highPriceNum)

    for i in range(math.floor(lowPriceNum),math.floor(highPriceNum+1)):
        #range()が出力するのは、(highPriceNum-1)なので1を加算してhighPriceNum分までを計算させる
        print('barPrice:',i*priceRange)
        #i*priceRangeの位置でBarオブジェクトを作成する。
        # 3Dカーソルの位置を0,0,0
        bpy.context.scene.cursor.location=(0.0,0.0,0.0) 
        color=(0.8,0.5,0.8,0.8)
        add_text(str(i*priceRange), color,(1.8,0.1/3, (i*priceRange)*bairitsu+0.045))#0.045 is ajustment
        
        bpy.context.scene.cursor.location=(0.0,0.0,0.0)
        # 平板作成 26500bar1
        bpy.ops.mesh.primitive_cube_add(location=(0, 0, 0), size=2.0)
        bpy.ops.transform.translate(value=(0.0,0.1/2,(i*priceRange)*bairitsu))#26500*0.001
        bpy.ops.transform.resize(value=(2.0,0.06/6,0.01/6)) # 図形を変形
        bpy.context.object.data.materials.append(mat3) # 材質
        for obj in bpy.context.selected_objects:
            if obj.name=='Cube':
                obj.name='bar_'+str(i*priceRange) 
#end def
######################################################################
#main
######################################################################
count=0#count is Global
xmove=0.8#1# move distancs
bairitsu=0.001# size Global

print('this Code for reading CSV.')
print('>>>>>CSV出力>>>>>')
#ここからCSV出力用
checkLineCount=0
df=[]

#CSVを読み込む
ifile='/Users/toshiromaseda/Documents/blender/script/2021年1月14日日経.csv'
try:#ファイルが存在しないときのエラー処理try
    with open(ifile,'tr') as fin:
        for iline in fin:
            try:
                tmp=iline.strip().split(",")#stripしてからsplit()だと理解している。
                if 'High' in tmp[0]:
                    continue
                if len(tmp) < 6:#全部で6列存在する。
                    print('ERROR 列の数があっていません。少ないようです。行数:',checkLineCount)
                    break
                print('iline[]:',tmp[0])
                #ここから処理を入れていけばよい
                df.append(nikkeiClass(tmp[0],tmp[1],tmp[2],tmp[3],tmp[4],tmp[5]))
                checkLineCount+=1
            except:
                print ('error')
except FileNotFoundError as e: # FileNotFoundErrorは例外クラス名
    print("ファイルが見つかりません。パス、ファイル名を確認してください", e)
    ifile.close()
    sys._exit()#ファイルがなければ終了

#Stock date
n=maenohi=5
end = datetime.now()
start = end - timedelta(days=n)
#start = end - timedelta(days=maenohi)#end.day-7 changes
#start = datetime(end.year, end.month, end.day-7)
##土日があると表示させるローソク足の数が少ないので、数が満たされるまでループするためSleepを入れた
#大量のデータはCSVで取得してからローソク足にしたほうが良さそう

'''
x=0
while x<=(maenohi):
    start = end - timedelta(days=n)
    df=data.DataReader('^N225','yahoo',start,end)#3990.T,#^N225
    date=df.index# 日付
    time.sleep(3)
    print('len(date):',len(date))
    print('3秒待ち')
    x=len(date)
    n=n+1
print(df.head(8))
if len(date)==0:
    print('ERROR Can not get any Price data, Check internet or yahoo finance com.')
    sys.exit()
'''

# 既存要素削除
for item in bpy.data.meshes:
    bpy.data.meshes.remove(item)

for item in bpy.data.materials:
    bpy.data.materials.remove(item)
        
#bpy.ops.outliner.item_rename()
#2.立方体 location:図形の中心座標 size:立方体の一辺の長さ rotation:立体の回転角(rad)
#bpy.ops.mesh.primitive_cube_add(location=(0, 0, 0), size=1.0, rotation=(0, 0, 0))

# 2.材質の定義(赤色)
mat1 = bpy.data.materials.new('Red')
mat1.diffuse_color = (1.0, 0.0, 0.0, 1.0)

# 3.材質の定義(青色)
mat2 = bpy.data.materials.new('blue')
mat2.diffuse_color = (0.0, 0.0, 1.0, 1.0)

mat3 = bpy.data.materials.new('gray')
mat3.diffuse_color = (0.8, 0.8, 0.8, 0.5)

mat5 = bpy.data.materials.new('yellow')
mat5.diffuse_color = (1.0, 0.9, 0.1, 1.0)

# 3Dカーソルの位置を0,0,0
#bpy.context.scene.cursor_location =(0.0,0.0,0.0)
bpy.context.scene.cursor.location=(0.0,0.0,0.0)

#date=df.indexをカウントして、それぞれを取得する。ちょっとスマートではないが、、
for fdate in df:
    khigh=float(fdate.high)
    klow=float(fdate.low)
    kopen=float(fdate.open)
    kclose=float(fdate.adjclose)
    #ここに日付ごとの処理を入れる。
    #
    if kopen-kclose<0:
        candle='yousen'#color Red
        #print('陽線')
    else:
        candle='insen'#color Blue
        #print('陰線')
    #objを生成する。
    #始値、終値でZ軸の高さを設定する。
    #print( fdate.strftime("%Y/%m/%d") )#2020-12-22 00:00:00となるので、時刻を除く2020-12-22
    #Candle_Main####################################################
    candleLocation=fcandle(candle,kopen,kclose,bairitsu,xmove,mat1,mat2)
    xmove+=0.048
    
    #Candle_hige####################################################
    fcandle_hige(candle,khigh,klow,bairitsu,candleLocation,mat1,mat2)
    #count is Global      
    count+=1

#最後のローソクのobjの横に矢印を与える
#この場合、ローソクの原点を移動させて、ローソクの中心に移動させる必要がある
candleCount=0
for obj in bpy.data.objects:
    if 'candle' in obj.name:
        #print(obj.name)
        candleCount+=1
candleName='candle'+str(candleCount)

#Arrow
bpy.ops.mesh.primitive_cone_add(radius1=1, radius2=0, depth=2, enter_editmode=False, align='WORLD', location=(0, 0, 0), scale=(0.05, 0.05, 0.05))
#図形を回転(Y軸周りに90°)
bpy.ops.transform.rotate(value=-3.1415/2 ,orient_axis='Y')
bpy.context.object.data.materials.append(mat5) 
bpy.ops.transform.translate(value=(bpy.data.objects[candleName].location[0]+0.08,bpy.data.objects[candleName].location[1],bpy.data.objects[candleName].location[2]))#


bpy.context.scene.cursor.location=(0.0,0.0,0.0)
#open,close
color=(1.0,1.0,1.0,1.0)
#str,color,location,size
lastOpen=float(df[len(df)-1].open)#始値
lastClose=float(df[len(df)-1].close)#終値
roundOpen='O:'+str(round(lastOpen,2))#画面に表示させる直近の始値文字
roundClose='C:'+str(round(lastClose,2))#画面に表示させる直近の終値文字

add_textKai(roundOpen, color,(xmove+0.1,0,lastOpen*bairitsu),(0.06,0.05,0.06))
add_textKai(roundClose, color,(xmove+0.1,0,lastClose*bairitsu),(0.06,0.05,0.06))

#end.strftime("%Y/%m/%d") or date[len(date)-1].strftime("%Y/%m/%d")today
color=(0.0,1.0,0.0,1.0)
coneLocation=bpy.data.objects['Cone'].location
#tyokkinDay=date[len(date)-1].strftime("%Y/%m/%d")
tyokkinDay=df[len(df)-1].index

if len(df)>0:
    add_textKai(tyokkinDay,color, (coneLocation[0]+0.16,coneLocation[1],coneLocation[2]),(0.06,0.05,0.06))
#print('last day:',date[len(date)-1])

#始値、終値、直近の日付の調整。オブジェクトが重なってしまう金額が近いときに離す処理
if candle=='yousen':#Openが下側でCloseが上側にあるはず
    #bpy.data.objects[roundOpen].dimensions[1]#Z方向の幅サイズではなくてY軸、理由はローカルで回転させたから
    #bpy.data.objects[roundClose].dimensions[1]
    #bpy.data.objects[tyokkinDay].dimensions[1]
    #始値、終値、直近の日付のlocationを取得する。Z方向ではなくてY軸の幅の半分を上下に加減算して重なりを調べる
    #bpy.data.objects[roundOpen].location[2]
    #bpy.data.objects[roundClose].location[2]
    #bpy.data.objects[tyokkinDay].location[2]
    #roundCloseを調整する.roundCloseの下側位置が、直近日付の上側位置以下になっているときに、直近日付の上の方にroundCloseを上へ移動させる
    
    #location is [2]:Z, dimensions is [1]:Y
    if bpy.data.objects[roundClose].location[2]-bpy.data.objects[roundClose].dimensions[1]/2 <= bpy.data.objects[tyokkinDay].location[2]+bpy.data.objects[tyokkinDay].dimensions[1]/2:
        #直近日付の位置に、プラスへ移動
        bpy.data.objects[roundClose].location[2]=bpy.data.objects[tyokkinDay].location[2]+bpy.data.objects[tyokkinDay].dimensions[1]*1.5
    #roundOpenを調整する。roundOpenの「上側」位置が、直近日付の「下側」以上になっているときに、直近日付の「下の方」にroundOpenを下へ移動させる
    if bpy.data.objects[roundOpen].location[2]+bpy.data.objects[roundOpen].dimensions[1]/2 >=bpy.data.objects[tyokkinDay].location[2]-bpy.data.objects[tyokkinDay].dimensions[1]/2:
            #「マイナス」へ移動
        bpy.data.objects[roundOpen].location[2]=bpy.data.objects[tyokkinDay].location[1]-bpy.data.objects[tyokkinDay].dimensions[1]*1.5
else:#insen Openが上側でCloseが下側にあるはず.Yousenとは逆
    #roundOpen
    print('insen')
    if bpy.data.objects[roundOpen].location[2]-bpy.data.objects[roundOpen].dimensions[1]/2<=bpy.data.objects[tyokkinDay].location[2]+bpy.data.objects[tyokkinDay].dimensions[1]/2:
        bpy.data.objects[roundOpen].location[2]=bpy.data.objects[tyokkinDay].location[2]+bpy.data.objects[tyokkinDay].dimensions[1]*1.5
        print('Open')
    #roundClose
    if bpy.data.objects[roundClose].location[2]+bpy.data.objects[roundClose].dimensions[1]/2>=bpy.data.objects[tyokkinDay].location[2]-bpy.data.objects[tyokkinDay].dimensions[1]/2:
        bpy.data.objects[roundClose].location[2]=bpy.data.objects[tyokkinDay].location[2]-bpy.data.objects[tyokkinDay].dimensions[1]*1.5
        print('Close')

    

#2020/12/29
#print('Max:',max(df['High']))#最大値が取れる
#高値の最大値maxと安値の最小値minを取得して
#500円ごとのバー基準株価線(26500,27000,27500)を自動で作成したい。
#面倒だけど、別途高値、安値の配列オブジェクトを作って、メソッドに渡す
dfHigh=[]
dfLow=[]
for m in df:
    dfHigh.append(float(m.high))
    dfLow.append(float(m.low))

makeBarMaxtoMin(dfHigh,dfLow)

#camera move, near Cone obj
camera_obj = bpy.data.objects['Camera']
print(camera_obj.location)
camera_obj.location=(coneLocation[0]+0.16,coneLocation[1]-3.0,coneLocation[2])

#Neko呼び出し
file_path = '/Users/toshiromaseda/Documents/blender/model/テスト、研究モデル/Neko/Neko_simple_001.blend'
inner_path = 'Object'
object_name = 'Neko'
 
bpy.ops.wm.append(
    filepath=os.path.join(file_path, inner_path, object_name),
    directory=os.path.join(file_path, inner_path),
    filename=object_name
    )

bpy.context.scene.cursor.location=(0.0,0.0,0.0)
# 指定オブジェクトを取得する
#arg_objectname='Neko'
selectob = bpy.data.objects[object_name]
selectob.select_set(True) #2.9
selectob.location=(coneLocation[0],coneLocation[1]-0.1,coneLocation[2])
bpy.ops.transform.resize(value=(0.07,0.07,0.07)) # 図形を変形

print('done.')

''' Result



'''

 

python,株データ取得pandas_datareader 米ヤフーファイナンスからデータ欠落する時間帯があるメモ

#Blenderにpandas_datareaderインストール済

python,株データ取得のためのコード、Anaconda、JupyterLabで実行
#日経平均株価のデータを取得したときに、前日分が欠落することがあった。今日の分は取得できたのに、、、
#過去1週間のデータを取得とするはずだったが一部の日付データが取得できず。
#start: 2020/12/22
#today: 2020/12/29
#df=data.DataReader(‘^N225′,’yahoo’,start,end)
#しかし、午前中は 12/29当日データは取得できたけど、前日12/28分は取得できず。
#AM9-11ごろ x
#AM11:07分頃
#AM11:30 x
#11時53分 今度は28日が取得できて、今日の分が取得できず
#12:07 正常に取得できた。28日と今日の29日

結論:たぶん午前中は欠落するデータがあるかもしれない。午後12:05になると当日の日経平均株価が正常に取得できるようだ。正常に取得できないときは、日付が今日の分29日はあっても前日の28日がない。ちなみに25日分はあった

start: 2020/12/21
today: 2020/12/29
2020/12/21
2020/12/22
2020/12/23
2020/12/24
2020/12/25
2020/12/28>>午前中はこの日のデータが取得できず
2020/12/29>>午前中でも取得できた
                    High           Low          Open         Close  Volume  \
Date                                                                         
2020-12-21  26905.669922  26533.630859  26834.099609  26714.419922   60700   
2020-12-22  26639.990234  26361.660156  26559.330078  26436.390625   58600   
2020-12-23  26585.210938  26414.740234  26580.429688  26524.789062   56000   
2020-12-24  26764.529297  26605.259766  26635.109375  26668.349609   47900   
2020-12-25  26716.609375  26638.279297  26708.099609  26656.609375   33400   
2020-12-28  26854.029297  26664.599609  26691.289062  26854.029297   50700   
2020-12-29  27298.220703  26921.140625  26936.380859  27292.369141       0   

               Adj Close  
Date                      
2020-12-21  26714.419922  
2020-12-22  26436.390625  
2020-12-23  26524.789062  
2020-12-24  26668.349609  
2020-12-25  26656.609375  
2020-12-28  26854.029297  
2020-12-29  27292.369141