UdemyでPythonを勉強した結果を残すブログ。

40歳でプログラミング始めて転職までいけるのかを実録してみます。

pythonで日本株のシステムトレードを開発する

pythonを再開してみる。 実績と趣味として株式のスクリーニング、トレードツールまでつくれたらいいなという感じでやってみる。

以下要件定義をリストアップする。

  • 全ての銘柄コードを取得する。
  • 取得した銘柄コードの株価などのデータをcsvに保存していく。
    • 1回保存されたcsvがあれば、前回保存したデータ以降のデータを追記する。
    • 最新の場合はスルー
  • チャートやインジケーターとかをチャートに反映できるようにする
    • 欲しいインジケーターはrsi、macdrci、騰落レシオ
  • インジケーターを調整して結果をリアルタイムで反映できるようにしたい
  • バックテストができて勝率とかドローダウン、期待値とかを表示できるようにしたい

gasp使い方

とりあえずざっくりコード

import {gsap} from "gsap";
import { useEffect, useRef } from "react";
import ScrollTrigger from "gsap/src/ScrollTrigger";
/** @jsImportSource @emotion/react */
import { css} from "@emotion/react";


export default function Top() {

    useEffect(() => {
        gsap.registerPlugin(ScrollTrigger);

        // 各画像要素のアニメーション
        const scrollphotos = gsap.utils.toArray(".scrollphoto");
        scrollphotos.forEach((el) => {
            const tl = gsap.timeline();
            ScrollTrigger.create({
                trigger:el,
                start: "top center",
                end: "bottom center",
                once: true,
                onEnter: () => {
                    const h3element = el.querySelector('.scrollphoto-title');
                gsap.fromTo(h3element, {width:"0", overflowX: "hidden"}, {width:"200px", delay:1.5, duration:2});
                popup(el);
                }
            });

            function popup(el) {
                tl.fromTo(el, {x:-1000, autoAlpha:0}, {x:0, ease:"boue.inOut", duratioin:1.5, autoAlpha:1})
            }
        }, []);
        const tl2 = gsap.timeline();
        tl2.to('.my-element2 span', {x:100, ease:"bouce.out", fontSize:'2.5em', duration:2})
    });

    return ( 
        <div css={wrapBox}>
            <div className="my-elemtent2" css={fontBox}>
                <span>Hello,world</span>    
            </div>
            <div className="scrollphoto" css={scrollphoto}>
                <h3 className="scrollphoto-title" css={photoTitle}>Photo1</h3>
                <img src="images/card-1.webp" alt="" />
            </div>
            <div className="scrollphoto" css={scrollphoto}>
                <h3 className="scrollphoto-title" css={photoTitle}>Photo2</h3>
                <img src="images/card-2.webp" alt="" />
            </div>
            <div className="scrollphoto" css={scrollphoto}>
                <h3 className="scrollphoto-title" css={photoTitle}>Photo3</h3>
                <img src="images/card-3.webp" alt="" />
            </div>
        </div>
        
    )
}

javascriptでいろんな要素を取得するとりあえずの一覧

ざっくりとDOM要素の取得関数一覧。

querySelectorとquerySelectorAllでほぼ大丈夫だけど ページ数が多かったりするときはgetElementBy... の方が処理が早いのでいいらしい。

詳細の要素を指定したい場合などはページ数が多くても併用する。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h1>h1タイトル</h1>
    <p id="pId" class="Attr">段落<span>スパン</span></p>
    <p class="Attr">段落2<span>スパン2</span></p>
    <p class="Attr">段落3</p>
    <input type="text" name="nameAttr">
    <input type="password" name="pwdAttr">
  <script>
    const pid = document.getElementById("pId");
    console.log(pid);
    const getClassAttr = document.getElementsByClassName("Attr");
    console.log(getClassAttr)
    const getPAll = document.getElementsByTagName("p")
    console.log(getPAll)
    const getNameTypeText = document.getElementsByName("text");
    const getParentSpan = document.querySelector("span");
    const getParentSpan2 = getParentSpan.closest("p")
    const getH1broTypePass = document.querySelector('h1 ~ [name = "pwdAttr"]');
    const getChildpId = document.querySelector('#pId > *')
    const getNextText = document.querySelector('input + [name="text"]');
    console.log(getNameTypeText)
    console.log(getParentSpan2)
    console.log(getH1broTypePass)
    console.log(getChildpId)
    console.log(getNextText)
  </script>
  </body>

</html>

取得したHTMLを表示・編集などする

console.log(getPAll[1].innerHTML)
console.log(getPAll[0].textContent)

javascriptで外部からデータをfetchで取り込む

jsonなどのデータを取り込んで処理していくのはfetch

<script>
fetch("sample.json")
    .then( response => response.json() )
    .then( data => { 
        for (const {key,value} of data) {
            console.log(key + ":" + value); 
        }
    });

// awaitを使った場合
async function myFetch() {
    const response = await fetch("sample.json");
    const data = await response.json();
    for (const {key, value} of data) {
        console.log(key + ":" + value)
    }
}

myFetch()
</script>

sample.json

[
    {"key": "apple", "value": "リンゴ" },
    {"key": "orange", "value": "オレンジ" },
    {"key": "melon", "value": "メロン" },
]

DAY45 Beautiful Soupを使ってスクレイピングをする

Beautiful Soupを使ってスクレイピングをする

目次

概要

今回はrequestsとBeautiful Soupというプラグインをインポートしてウェブサイトのデータを取得するスクレイピングの簡単な部分を勉強します。

簡単に言えばpythonでサイトのソースを保存して、欲しいところだけクリッピングができるということ。

例えばそのサイトのリンク先だけ保存するとか、画像リンクだけを取得するとか。

それでは始めます。今回は結構簡単ですが、HTMLをある程度理解していることが前提です。

requestsとBeautiful Soupをインストールして呼び出す

1ページのみなら、使い方は一度さらえばとても簡単。

import requests
from bs4 import BeautifulSoup

re = requests.get("https://news.yahoo.co.jp/topics/business")
page = re.text

soup = BeautifulSoup(page, "html.parser")

titles = soup.find_all("div", {"class":"newsFeed_item_title"})

for title in titles:
    print(title.text)

例えば、このコードでは

経済トピックス一覧 - Yahoo!ニュース

ここのタイトルリストを表示されている分を取得しています。

  • requests.getにurlを入れてソースを取得
  • re.textにすることでオブジェクトからテキストに変換
  • soupという変数でBeautiful Soupを呼び出し、pageの変数をhtml.parserという機能で解析する
  • 解析したhtmlからfind_allという機能でhtmlソースのnewsFeed_item_titleというクラスを持つdivを全部抽出し、titlesという配列で保存
  • titlesの配列から1つずつprintでコンソールに出力

という流れです。

基本的にはこれがテンプレな感じでスクレイピングができますが、 普通は複数のページとかやりたいのでその辺はまた後日勉強していきたいと思います。

よりわかりやすいサイトはこちらとか

図解!Python BeautifulSoupの使い方を徹底解説!(select、find、find_all、インストール、スクレイピングなど) - AI-interのPython3入門

DAY38 pythonでデータをトラッキングしてGoogle sheetsにまとめる!

PythonAPIを使ってGoogle Sheetsを連携した作業を学ぶ

目次

2つのAPIを使って何をしたかをデータでまとめる

コンソールにその日に何のエクササイズをしたかを答えるだけでこんな感じでAPIが数値を判断してGoogle Sheetに入力してくれます。 カロリーまで入力してくれる! Nutritionist のAPIを使います。

nutritionix_apiを利用してエクササイズのカロリーを出力してもらう

www.nutritionix.com

nutritionixのサイトへいき、freeを選んでIDとAPI keyを取得します。

pythonのプロジェクトのmain.pyと同じ階層に.envを入れて、API KEYとIDを入力しておきます。

.env
ENV_NUTRITION_ID = "iddayo"
ENV_NUTRITION_KEY = "keydayo"

python-dotenvのパッケージをインストールしてから、読み込みをします。
テンプレはこちら

import os
from dotenv import load_dotenv
from os.path import join, dirname
load_dotenv(verbose=True) #.envファイルが見つからない時にエラーを出す
dotenv_path = join(dirname(__file__), '.env')
load_dotenv(dotenv_path)

次にnutritionのドキュメントを見ます。

Nutritionix - Track API V2

今回はエクササイズを入力したいので、 エンドポイントは/v2/natural/exerciseになります。

みる感じ

x-user-jwt →apiのidとkeyがheaderとしている query → 質問内容を文章にする gender,weight_kg,height_cm,age 性別、体重、身長、年齢

がいるようなのでこれらも変数定義しておきます。

apiを読み込むときはrequestsがいるので、先にpackageでインストールをするのを忘れずに。

Nutritionix API v2 - Documentation [PUBLIC] - Google ドキュメント

ここのObtaining API Keys & Authenticating部分をみると、 apiのIDとKEYはデータを送信するときは x-app-id、x-app-keyと名付けて入力するとのこと。(gender : 30,みたいに x-app-id: ID という感じ)

あと同じページでExcecise Endpointsをみると、requestはpostにするとのことなのでこれらを理解してからコーディングすると


import requests
import os
from dotenv import load_dotenv
from os.path import join, dirname
load_dotenv(verbose=True) #.envファイルが見つからない時にエラーを出す
dotenv_path = join(dirname(__file__), '.env')
load_dotenv(dotenv_path)
GENDER = "male"
WEIGHT_KG = 56
HEIGHT_CM = 168
AGE = 27

NUTRITION_ID = os.environ.get("ENV_NUTRITION_ID")
NUTRITION_KEY = os.environ.get("ENV_NUTRITION_KEY")
NUTRITION_ENDPOINT = "https://trackapi.nutritionix.com/v2/natural/exercise"

def get_nutrition_data():
    exercise_text = input("何のエクササイズを何分した?英語で(e.g. ran 15min, swam 30min, walked 1hour): ")

    headers = {
        "x-app-id": NUTRITION_ID,
        "x-app-key": NUTRITION_KEY,
    }
    parameters = {
        "query" : exercise_text,
        "gender": GENDER,
        "weight_kg": WEIGHT_KG,
        "height_cm": HEIGHT_CM,
        "age": AGE,
    }
    r = requests.post(NUTRITION_ENDPOINT, headers=headers, json=parameters)
    result =r.json()
    print(result)


get_nutrition_data()

こんな感じになります。

試しにこれを起動させてみると、

こんな感じでjsonデータを吐き出してくれます。 今回は45分走ったと答えると大体500kcalくらいの消費になるようですね。

Sheetyを利用してSpreadSheetを連携する

sheetyを利用する前に先にスプレッドシートを作っておきます。 表はこんな感じ。

sheety.co

シート作成後にsheetyというサイトへ行き、googleアカウントと連携します。

プロジェクトを新規で作って、スプレッドシートのURLを入力するとこんな感じで読み込んでくれるので、Create Projectをクリック。

そうすると、APIのエンドポイントがGET、POSTなど別に表示される。 URL自体は同じだけど、記述方法はGETとPOSTで少し違うので注意。

GETの場合はデータを拾ってくるだけなので認証のみでよい感じだけど、POSTはどこのセルに何を入力するなど細かい設定も記述しなくてはいけない。

まずはGETを起動して動作するか確認してみる

nutrition apiと同じような感じで、まずはシートのデータを取得する機能を作ってみる。

SheetyのAuthenticationを設定して、Tokenも適当に入力すると、下のAuthorization Headerというところが変わる。ここをheaderを定義していれる。

SHEET_ENDPOINT = "sheety no url dayo"
def get_sheets_data():
    headers = {
        "Authorization": "Bearer tokendayo"
    }

    r = requests.get(SHEET_ENDPOINT, headers=headers)
    result = r.json()
    print(result)

とこんな感じになる。

POSTで書いてみる

GETで無事データが取得できたので、POSTでも書いてみる。

今回はDate,Time,Exercise,Duration,Caloriesの5項目を入力するので、配列でフォーマットを作る。
また、最初に作ったget_nutrition_data()は複数のエクササイズを1度に入力できるので、その度に入力できるようにfor文を使う。

def put_sheets_data():
    result = get_nutrition_data()
    result = result["exercises"]
    for exercise in result:
        sheets_params = {
            "workout": {
                "date": today,
                "time": time,
                "exercise": exercise["user_input"].title(),
                "duration": exercise["duration_min"],
                "calories": exercise["nf_calories"]
            }
        }
        re = requests.post(SHEET_ENDPOINT, headers=headers, json=sheets_params)
        print(re.text)

最初に作ったget_nutrition_data()からjsonデータを取得して、
そのjsonから抜き出したい階層まで移動してからパラメーターを作っています。

for文を使うことで["exercises"]配列から1データずつを入力することで、
ranは15分、カロリー
walkedは14分、カロリー とスプレッドシート1行ずつに入力することができます。

gitはこちら。

github.com