Github Copilotを使わずVSCodeにContinueを入れて使ってみる

無料で使えるAIツール「Continue」でVSCodeにAIコード補完機能を導入する方法 Github Copilotが出てだいぶ時間が経ちましたが、IDEで未だにAIを使わず開発をしています。 Github Copilotは料金がかかりますし、open-interpreterを使ったとしてもopenAIのapiを使ってるので料金はかかります。 結果ほぼIDEでAIを使わずやってきたのですが、最近Continueが出たということを聞きました。こちらはllamaなどのオープンソースを使ってるので、料金はかからなそうです。参考にした記事はこちらになります。Continueのサイトはこちらです。llamaの使い方はこちら。 Continueのインストール手順 というわけでまずはインストールしてみます。 インストールが完了すると左のタブに表示されます。モデルの選択でどのモデルを使用するか選ぶことができます。 Llamaモデルのダウンロードと設定 チュートリアルに従って次はllamaをダウンロードします。こちらですね。最近llama3.2が発表されたので3.2になってますね。3.1が良ければこちらからダウンロードできます。 次にOSを選んでダウンロードしましょう。もしモデルのアップデート通知が欲しければアカウントを作って登録すると良いと思います。ニュースになるので今はやらなくてもいいかと ターミナルでモデルを実行 実行ファイルがダウンロードされるので開いて案内に従っていきます。インストールが完了すると実行ファイルなどが入っています。実行するとコマンドプロンプトから実行してくださいと言われます。 というわけでターミナルを開いて以下のコマンドを実行します。チュートリアルでは3.1:8bとなってますが、今回は3.2:3bを使用します。 ollama run llama3.2:3b 大きなモデルの利用(任意) 一応チュートリアルではGroqとtogetherなどのサイトのAPIを使えば大きなモデルも使うことができるみたいです。ただ、料金などもかかりますので今回は省きます。 Continueのモデル設定とconfig.jsonの編集 最初のモデル選択の部分でFree Trialのモデルを使えます。こちらを使う場合はGitHubにサインインする必要があります。今回はllamaをインストールしたのでlocal modelを使うことになります。 次はconfig.jsonを編集していきます。llama3.1を使う場合はこの"Add Chat model"から設定できますが、今回は3.2なのでconfig.jsonを直接編集していきます。Free Trialが不要であれば削除しましょう。編集する際は歯車を押せばconfig.jsonを開きます。 エラー対処とモデルの接続 文字を入力してみましたが、エラーが出ました。大元のモデルは動いてますが、チャットモデルも必要みたいです。オートコンプリートモデルはコーディングをするとき予測して文字を補完するモデルです。というわけでpullしてみます。 コマンドのターミナルをクリックすればターミナルにコマンドがコピーされますので、pullしましょう!もしこんなエラーが出たらおそらくVSCodeがポートを使用しているのでターミナルから実行してみてください。 Error: Head "http://127.0.0.1:11434/": dial tcp 127.0.0.1:11434: bind: An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full. 両方のモデルをpullすれば無事接続ができます。接続した際、llama3.1のモデルがconfigに追加されます。まあtitleやmodel名は違いますが消しても大丈夫です。接続できたことを確認できれば、初めのconfigで設定したモデルを使用できるようになります。 Continueを実際に使ってみる というわけで使えるようになりました。もちろんChat-GPTやCloudeのほうが性能がいいと思います。ノートPCで使えるローカルモデルではないですし。ただ、ネットにつながず軽量なモデルだとは思いますのでもう少し試してみようと思います。 ...

2024年9月30日

機械学習の無料講座をGoogleが出しているので受けてみたよ

E資格合格後に再学習を決意した理由 E資格を合格した後復習とか出来てないので、改めて学びなおしてみようと思ったのがきっかけになります。こちらから受けることができます。必要に応じて日本語に切り替えることもできます。 生成AIの進歩もありそれにまつわるような部分もあるので、ぜひ理解を深めたうえで使っていくと良いと思います。 機械学習講座の学習ツールとインターフェース タブに基礎コースと上級コースがあるのでまずは基礎コースからやってみました。 初めの内容としてはこんな感じですね。 右タブに情報とチャットとAPIがあります。 情報はこのページの目次ですね。チャットは生成AIを使って質問することができます。わからないことがあったら随時聞いてみるといいと思います。サービスの同意をしたら試してみましょう! APIを使えばデータを見ることができます。一覧はこちらにあります。今回は一旦無視しますね。 理解度チェックとインタラクティブな学習 目次の項目によっては理解度チェックがあります。下の画像の場合は三択から1つ選んでクリックすることになります。日本語だと微妙な部分もありますので、英語で見てみるのも手ですね。 正解の選択肢では説明を見られるものもあります。間違った場合は別の選択肢をクリックしましょう。間違ってもペナルティがあるわけではないので、ミスは気にせずページをよく読んで解答するとよいです。 動画コンテンツでの学習補助 さらに動画もあります。概要の説明をしているので興味があれば見てみてください。英語説明ですが画面を見てるとなんとなくわかるので、必要であれば字幕を付けるなどして見てください。 基礎講座だけでも十分機械学習について学ぶことができます。一応上級講座も見てみました。 基本的に変わりませんが、前提知識や実装経験が必要になってきます。 なのでまずは基礎で十分理解と実装経験を積んでから上級に行くことをおすすめします。 機械学習のプログラミング演習活用 講座を進めていくとプログラミング演習を実施することもできます。英語なので必要に応じて日本語訳してみてください。 機械学習講座後のバッジとプロフィールの公開 学習が終わってチェックテストをクリアするとバッジをもらうことができます。お気に入りを5つまで設定できるので、いっぱい集めてみようと思います。 プロフィールを公開すれば他の人にも見られるようになります。転職等で使えるんですかね? 今後の学びと実践に向けた決意 機械学習には教師あり、教師なし、強化学習、生成があります。本来全てやることは少ないかと思うので全て学ぶにはかなり時間がかかると思います。 ただ、これが理解できればどのようなデータが仕事に使えるかわかるようになります。また売上予測や顧客分類、キャンペーンの効果も見える部分が出てくると思います。 しっかり学んで実際のデータで試してみれば学習の実感が出てくると思うので頑張っていきましょう!私も再度学びなおして理解を深めていきます。ではでは。

2024年9月14日

人間っぽいふるまいをするスクレイピングを検討した話

前提:利用規約に違反しないこと 前提として利用規約に違反する行為はやめたほうが良いと考えています。 法的に訴えられても文句は言えないですし。 多くの人が利用しているamazonなども利用規約で禁止しているので、スクレイピングをする際はしっかりと利用規約を読んだうえで行ってください。許可が下りれば問題ないとは思いますが。 サイト側のスクレイピング対策 本題に入ります。 サイト側でスクレイピングを弾く設定がいくつか存在します。例えばユーザーっぽくないふるまいでサイトにアクセスした場合。あるいは特定のサイトを経由しないと見れないURLに直接アクセスした場合。ゆうまでもなく連続でいろんなURLにアクセスした場合。 連続でアクセスされるとサーバーに負荷がかかるので、これが弾かれるのは想像に難くないと思います。 スクレイピング対策を避ける方法 ただ、スクレイピングするされた場合、上記のような特徴が存在します。 この辺はアクセスログを監視すると見れるかと思います。おそらくですが。 では人間っぽくふるまうにはどうしたらよいか調べた中で書いてみます。 一応言語はpythonを使います。他の言語でもできるかと思うので参考程度にはなるかと思います。 Pythonでのスクレイピング基礎 一般的にpythonでのスクレイピングではrequestsモジュールを使います。他にもseleniumやpyppeteerなどがありますが、一旦requestsを使っていきます。 インストールはpipを使います。 pip install requests もしpythonのバージョンなどで分けてる場合はこちら py -3.12 -m pip install requests インストールが終わったらアクセスしてみましょう。今回は私のサイトにアクセスしてみます。 import requests response = requests.get('https://xainome.blog/’) print(response.text) こうするとHTMLの中身を取得することができます。 そこから取得したい情報があればBeautifulSoupを使って要素を取り出してみましょう。まずはインストール pip install beautifulsoup4 実際のアクセスとHTMLの解析 インストールができたらHTMLを解析します。 from bs4 import BeautifulSoup soup = BeautifulSoup(html_parse, 'html.parser') これで解析の準備ができました。解析の話は本題とそれますのでここまでにしようと思います。 解析やHTMLの情報取得に興味があれば調べてもいいですし、生成AIに聞いてみるでもいいと思います。このようなコード、銘柄、市場などが一覧で取得することができます。もちろんAPIを使うという手もありますが。 リクエストヘッダーの設定 実は通常のリクエストを送る場合ユーザーではなく、言語別のリクエストを送っていることになります。 リクエストにはRequests Headersというものが設定できます。これは私たちがPCやスマホでサイトにアクセスするときも送信されています。 まずは設定してみます。 headers = { 'User-agent' = 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36' } response = requests.get(search_url, headers=headers) こんな感じで設定します。特に何も設定しなかった場合、‘python-requests/2.25.1’という設定で送られるみたいです。恐らくjsやGoとかでも似たような設定になるかと思います。 ...

2024年8月30日

PrefectとBigQueryを使っているので現状やったことを書いてみる

副業でのPrefect CloudとBigQueryの使用 副業でPrefect CloudとBigQueryを使っているので触った点と書いてみようと思います。 環境の設定とインストール 私はWindowsを使っています。契約を結んでいる企業の導入手順がMacで書かれていたのでそこもいろいろ調べてやってみました。 Prefectとは? そもそもprefectとは何ぞや?というところですね。prefectはPythonベースのワークフローエンジンになります。 pythonジョブの実行を自動化したりデバッグしたりする機能をpythonコードで書けるシステムになります。 AWSだとStepfunctionのイメージに近いですね。それに加えてEventBridgeやCloud Watch Logsが足されたような感じです。 おそらくAWSやGoogle Cloudに比べてコストが低く、使いやすいという点で採用されたと考えられます。 Prefectの参照しているドキュメントはこちらです。ちなみに3.0がリリースされたみたいなのでそちらのドキュメントはこちらになります。 インストール手順 一応pythonをインストールしている前提でお話しします。 まずはprefect cloudのインストールを行います。 pip install prefect 次はタスクを実行するためのコマンドが必要になります。ただ、Windowsにはパッケージ管理ツールがありません。 なくても問題ないですが、せっかくなので導入してみます。今後パッケージを入れるときは活用していきたいです。 Scoopの導入 今回使ったパッケージはscoopになります。手順はサイトにあるのでコマンドプロンプトに入力します。 Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser デフォルトでmainがありますが、もしバケットを別にして管理したい場合は以下のコマンドを使います。 # バケットの追加 scoop bucket add extras # バケット一覧 scoop bucket list # インストール一覧 scoop list 今回はtaskだけ必要なのでmainに入れました。これでtaskコマンドが使えるようになります。 Prefectの設定と実行 ただ、taskを実行するにはTaskfile.yamlが必要になります。中身はプロジェクトによりますが私がやったのはこんな感じ。全部ではないですが… tasks: start-local: cmds: - pip install -r requirements.txt - prefect config set PREFECT_API_URL=http://127.0.0.1:4200/api - prefect server start start-local-agent: cmds: - prefect config set PREFECT_API_URL=http://127.0.0.1:4200/api Taskfile.yamlの準備が出来たらターミナルの用意します。 ...

2024年8月23日

SageMakerエンドポイントを利用してモデル管理を調べた話

AWSを使用してAIモデルを複数管理する方法 AWSを使用してAIのモデルを複数管理したいという話がありました。 学習済みのモデルなので本番では推論しか使われませんが、モデルのバージョン管理を行いたいということだったので調査をしました。 S3にモデルを置くだけでもある程度管理はできますが、SageMakerのエンドポイントを使うかもしれないということでSageMakerでの管理を調べることになりました。 基本的な書き方はサンプルの書き方に沿ってます。こちらです。 モデルのS3へのアップロード まずはモデルをS3にアップロードするところからです。 # tensorflowを使うのでmodel.tar.gzにモデルを固める TAR_DIR = './tmp' # 一時的なモデルディレクトリ CODE_DIR = './code' # infarence.py等のディレクトリ MODEL_DIR = './model' # モデルディレクトリ TAR_NAME = os.path.join(TAR_DIR , 'model.tar.gz') with tarfile.open(TAR_NAME, mode='w:gz') as tar tar.add(MODEL_DIR) tar.add(CODE_DIR) # モデルをS3にアップロード(複数モデルをアップロードする想定) s3_uri1 = sagemaker.session.Session(default_bucket='development').upload_data( path = TAR_NAME key_prefix = 'image_recognition/test/model1' ) s3_uri2 = sagemaker.session.Session(default_bucket='development').upload_data( path = TAR_NAME key_prefix = 'image_recognition/test/model2' ) イメージの作成 モデルをアップロードしたら次はイメージの作成をします。イメージに関しては1イメージで複数モデル格納できますが、未調査のため一旦複数イメージを作成します。 image_uri1 = sagemaker.image_uris.retrieve( framework='tensorflow', region=sagemaker.session.Session().boto_region_name, version='2.12', instance_type='ml.m5.xlarge', image_scope=inference' ) image_uri2 = sagemaker.image_uris.retrieve( framework='tensorflow', region=sagemaker.session.Session().boto_region_name, version='2.12', instance_type='ml.m5.xlarge', image_scope=inference' ) モデルパッケージグループの作成 モデルパッケージグループの作成をします。この中にモデルを複数入れることでバージョン管理を行っていきます。 ...

2024年8月3日

短期売買と分析力が向上しそうな株価予測をだらだらとやる part9

前回のあらすじ 確率的勾配降下法を使って予測をしてみました。 うまくいかなかったので、別の方法を試すことにしました。 LSTM 時系列分析の代表モデルと言えばLSTMだと思います。 というわけで前回とはプログラムを分けて実装しました。 import pandas as pd import numpy as np from sklearn.preprocessing import MinMaxScaler from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense, LSTM, Input import matplotlib.pyplot as plt import glob dm_fol = './datamart/' stock_list = glob.glob(dm_fol + "*.parquet") # データの読み込みと前処理 def preprocess_data(df, time_step=60): df['Close'] = df['Close'].astype(float) data = df[['Close']].values # データのスケーリング scaler = MinMaxScaler(feature_range=(0, 1)) scaled_data = scaler.fit_transform(data) # LSTM用のデータセット作成 X, Y = [], [] for i in range(time_step, len(scaled_data)): X.append(scaled_data[i-time_step:i, 0]) Y.append(scaled_data[i, 0]) X, Y = np.array(X), np.array(Y) X = X.reshape(X.shape[0], X.shape[1], 1) return X, Y, scaler # LSTMモデルの構築 def create_lstm_model(input_shape): model = Sequential() model.add(Input(shape=input_shape)) # Inputオブジェクトを使用して入力形状を指定 model.add(LSTM(50, return_sequences=True)) # model.add(LSTM(50, return_sequences=True, input_shape=input_shape)) model.add(LSTM(50, return_sequences=False)) model.add(Dense(25)) model.add(Dense(1)) model.compile(optimizer='adam', loss='mean_squared_error') return model # モデルの評価とプロット def evaluate_model(df, model, scaler, X_train, y_train, X_test, y_test, time_step, sticker_name): y_train_pred = model.predict(X_train) y_test_pred = model.predict(X_test) y_train_pred = scaler.inverse_transform(y_train_pred) y_test_pred = scaler.inverse_transform(y_test_pred) y_train = scaler.inverse_transform([y_train]) y_test = scaler.inverse_transform([y_test]) train_mse = np.mean((y_train_pred - y_train[0]) ** 2) test_mse = np.mean((y_test_pred - y_test[0]) ** 2) print(f"Train Mean Squared Error: {train_mse}") print(f"Test Mean Squared Error: {test_mse}") # プロット df.set_index('Date', inplace=True) train_dates = df.iloc[time_step:len(y_train[0])+time_step].index test_dates = df.iloc[len(y_train[0])+time_step-1:-1].index plt.figure(figsize=(14, 7)) # plt.plot(train_dates, y_train[0], label='Train Actual', color='black') plt.plot(test_dates, y_test[0], label='Test Actual', color='red') plt.plot(test_dates, y_test_pred, label='Test Predicted', color='blue') plt.title(sticker_name+': Actual vs Predicted Stock Prices') plt.xlabel('Date') plt.ylabel('Close') plt.legend() plt.show() # 次の日の予測 def predict_next_day(model, scaler, df, time_step=60): data = df[['Close']].values last_data = data[-time_step:] last_data_scaled = scaler.transform(last_data) X_input = last_data_scaled.reshape(1, time_step, 1) next_day_prediction = model.predict(X_input) next_day_prediction = scaler.inverse_transform(next_day_prediction) print(f"Next Day Prediction: {next_day_prediction[0][0]}") # データの読み込み for count, stock_data in enumerate(stock_list): df = pd.read_parquet(stock_data) sticker_name = stock_data.split('\\')[1].replace('.parquet', '') # データの前処理 time_step = 60 X, Y, scaler = preprocess_data(df, time_step) # データの分割 train_size = int(len(X) * 0.8) X_train, X_test = X[:train_size], X[train_size:] y_train, y_test = Y[:train_size], Y[train_size:] # モデルの構築と訓練 model = create_lstm_model((X_train.shape[1], 1)) model.fit(X_train, y_train, batch_size=1, epochs=1) # モデルの評価 evaluate_model(df, model, scaler, X_train, y_train, X_test, y_test, time_step, sticker_name) # 次の日の予測 predict_next_day(model, scaler, df, time_step) コード確認 # LSTM用のデータセット作成 X, Y = [], [] for i in range(time_step, len(scaled_data)): X.append(scaled_data[i-time_step:i, 0]) Y.append(scaled_data[i, 0]) X, Y = np.array(X), np.array(Y) X = X.reshape(X.shape[0], X.shape[1], 1) LSTM用のデータセットは60日分のデータを学習として使い、次の日を出力として使用するという特徴があります。 ...

2024年7月24日

短期売買と分析力が向上しそうな株価予測をだらだらとやる part8

前回のあらすじ 株価予測を行うコードをいったん書いてみました。 課題はまだ残ったままですが、今回はそこを解決しつつモデルを追加で学習するというやり方を試してみました。 確率的勾配降下法 def predict_next_day(model, scaler, df): last_row = df.drop(columns=['Close']).iloc[-1].values.reshape(1, -1) # last_row = df.iloc[-1, :-1].values.reshape(1, -1) df.drop(columns=['Close']).iloc[-1].to_csv("test.csv") last_row_scaled = scaler.transform(last_row) next_day_prediction = model.predict(last_row_scaled) print(f"Previous Day Prediction: {df.iloc[-1]['Close']}") print(f"Next Day Prediction: {next_day_prediction[0]}") 前回の予測部分ですが予測するカラムが異なっていたので変な値が出ていました。 修正したことによってだいぶまともな値に修正ができました。 ただ、うまくいくときはきれいな形になっていますがそうでないことも多いです。 波があるところはうまくできている方ですが、直線気味だとうまくいかないですね。 毎回初期化しているのですが、ダメですね。使ってるモデルが確率的勾配降下法も要因としてあるかもしれないです。 というわけで追加学習する形に変更しようと試してみました。 def update_model(model, scaler, new_df): target = new_df['Close'].shift(-1).dropna() features = new_df.drop(columns=['Close']) features = features[:-1] # データのスケーリング X = scaler.transform(features.values) y = target.values model.partial_fit(X, y) # 新しいデータに対する予測と評価 # X_new = scaler.transform(new_df.drop(columns=['Close']).values) X_new = scaler.transform(new_df.drop(columns=['Close']).iloc[:-1].values) y_new = new_df['Close'].shift(-1).dropna().values y_new_pred = model.predict(X_new) mse_new = mean_squared_error(y_new, y_new_pred) print(f"New Data MSE: {mse_new}") for count, stock_data in enumerate(stock_list): ・ ・ ・ if count == 0: model, scaler, X_train, X_test, y_train, y_test = train_model(df) # モデルの評価 y_pred = evaluate_model(model, X_test, y_test) else: update_model(model, scaler, df) ...

2024年7月15日

短期売買と分析力が向上しそうな株価予測をだらだらとやる part7

前回のあらすじ オシレーター系指標の説明変数を追加するコードを書きました。 株価予測_コード 今回やることは株価の予測になります。 今回は1ファイルずつ読み込んで実行しています。ティッカーリストがあればティッカーごとにダウンロードしてきて加工する方法もあったのでいずれやります。 import pandas as pd import numpy as np import yfinance as yf from sklearn.linear_model import SGDRegressor from sklearn.metrics import mean_squared_error from sklearn.preprocessing import StandardScaler from sklearn.model_selection import train_test_split import matplotlib.pyplot as plt dm_fol = './datamart/' import glob stock_list = glob.glob(dm_fol + "*.parquet") def preprocess_data(df): df.sort_values('Date', inplace=True) # 日付を特徴量に変換 df['Year'] = df['Date'].dt.year df['Month'] = df['Date'].dt.month df['Day'] = df['Date'].dt.day df['Weekday'] = df['Date'].dt.weekday df['Quarter'] = df['Date'].dt.quarter # 周期成分のエンコーディング df['Month_sin'] = np.sin(2 * np.pi * df['Month'] / 12) df['Month_cos'] = np.cos(2 * np.pi * df['Month'] / 12) df['Day_sin'] = np.sin(2 * np.pi * df['Day'] / 31) df['Day_cos'] = np.cos(2 * np.pi * df['Day'] / 31) df['Weekday_sin'] = np.sin(2 * np.pi * df['Weekday'] / 7) df['Weekday_cos'] = np.cos(2 * np.pi * df['Weekday'] / 7) # 日付を削除 df.drop(columns=['symbol','Date'], inplace=True) # "symbol"以外のobject型カラムをワンホットエンコーディング df = pd.get_dummies(df, columns=[col for col in df.select_dtypes(include=['object']).columns]) # 全ての値が欠損している列を削除 df.dropna(axis=1, how='all', inplace=True) # 値が欠損している行を削除 df.dropna(axis=0, how='any', inplace=True) return df def train_model(df): target = df['Close'].shift(-1).dropna() features = df.drop(columns=['Close']) features = features[:-1] # データのスケーリング scaler = StandardScaler() X = scaler.fit_transform(features.values) y = target.values # データを7:3に分割 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42, shuffle=False) model = SGDRegressor(max_iter=1000, tol=1e-3) model.fit(X_train, y_train) return model, scaler, X_test, y_test def evaluate_model(model, scaler, X_test, y_test): y_pred = model.predict(X_test) mse = mean_squared_error(y_test, y_pred) print(f"Mean Squared Error: {mse}") plt.figure(figsize=(14, 7)) plt.plot(y_test, label='Actual', color='black') plt.plot(y_pred, label='Predicted', color='blue') plt.title('Actual vs Predicted Stock Prices') plt.xlabel('Sample') plt.ylabel('Price') plt.legend() plt.show() def predict_next_day(model, scaler, df): last_row = df.iloc[-1, :-1].values.reshape(1, -1) df.iloc[-1, :-1].to_csv("test.csv") last_row_scaled = scaler.transform(last_row) next_day_prediction = model.predict(last_row_scaled) print(f"Next Day Prediction: {next_day_prediction[0]}") # 初回データロードとモデル学習 # start_date = '1990-04-01' # end_date = '2024-07-03' # symbols = ['AAPL', 'MSFT', 'GOOGL'] for stock_data in stock_list: df = pd.read_parquet(stock_data) df = preprocess_data(df) model, scaler, X_test, y_test = train_model(df) # モデルの評価 evaluate_model(model, scaler, X_test, y_test) # 次の日の予測 predict_next_day(model, scaler, df) コードの内容 やったこととしては日付を特徴量に変換しました。 ...

2024年7月6日

短期売買と分析力が向上しそうな株価予測をだらだらとやる part6

前回のあらすじ トレンド系指標の説明変数を追加したところで終わりました。 オシレーター系指標 今回作成したのは RSI RCI 移動平均線乖離率 スローストキャスティクス モメンタムとROC MFI CCI ギャップ ヒストリカル・ボラティリティ def rsi(df): # RSIの計算 window = 14 # 終値の変化 df['Change'] = df['Adj Close'].diff() # 上昇幅と下落幅の計算 df['Gain'] = np.where(df['Change'] > 0, df['Change'], 0) df['Loss'] = np.where(df['Change'] < 0, -df['Change'], 0) # 平均上昇幅と平均下落幅の計算 df['Avg_Gain'] = df['Gain'].rolling(window=window).mean() df['Avg_Loss'] = df['Loss'].rolling(window=window).mean() # 相対力(RS)の計算 df['RS'] = df['Avg_Gain'] / df['Avg_Loss'] # RSIの計算 df['RSI'] = 100 - (100 / (1 + df['RS'])) # シグナルの判定 df['rsi_Signal'] = np.where(df['RSI'] > 70, 'Sell', np.where(df['RSI'] < 30, 'Buy', np.nan)) def calculate_rci(series): n = len(series) date_rank = np.arange(1, n + 1) price_rank = series.rank().values ssd = np.sum((date_rank - price_rank) ** 2) rci = 1 - (6 * ssd) / (n * (n ** 2 - 1)) return rci def rci(df): # RCIの計算 window = 14 df['RCI'] = df['Adj Close'].rolling(window=window).apply(calculate_rci, raw=False) # シグナルの判定(RSIと同様に70以上で売りシグナル、30以下で買いシグナル) df['rci_Signal'] = np.where(df['RCI'] > 70, 'Sell', np.where(df['RCI'] < 30, 'Buy', np.nan)) def madp(df): # 乖離率の計算 df['madp'] = (df['Adj Close'] - df['SMA']) / df['SMA'] * 100 # シグナルの判定 df['madp_Signal'] = np.nan threshold = 5 # 閾値の設定 for i in range(1, len(df)): if df['madp'].iloc[i-1] < -threshold and df['madp'].iloc[i] > df['madp'].iloc[i-1]: df.at[df.index[i], 'madp_Signal'] = 'Buy' elif df['madp'].iloc[i-1] > threshold and df['madp'].iloc[i] < df['madp'].iloc[i-1]: df.at[df.index[i], 'madp_Signal'] = 'Sell' def stochastic(df): # %Kの計算 window = 14 df['14-High'] = df['High'].rolling(window=window).max() df['14-Low'] = df['Low'].rolling(window=window).min() df['%K'] = (df['Adj Close'] - df['14-Low']) / (df['14-High'] - df['14-Low']) * 100 # スロー%Dの計算 df['slow%D'] = df['%K'].rolling(window=3).mean() # シグナルの判定 df['sto_Signal'] = np.nan for i in range(1, len(df)): if df['slow%D'].iloc[i-1] < 20 and df['slow%D'].iloc[i] > df['slow%D'].iloc[i-1]: df.at[df.index[i], 'sto_Signal'] = 'Buy' elif df['slow%D'].iloc[i-1] > 80 and df['slow%D'].iloc[i] < df['slow%D'].iloc[i-1]: df.at[df.index[i], 'sto_Signal'] = 'Sell' def momentum_roc(df): # モメンタムとROCの計算 window = 14 df['Momentum'] = df['Adj Close'] - df['Adj Close'].shift(window) df['ROC'] = ((df['Adj Close'] - df['Adj Close'].shift(window)) / df['Adj Close'].shift(window)) * 100 # トレンドの判定 df['Momentum_Trend'] = np.where(df['Momentum'] > 0, 'Uptrend', np.where(df['Momentum'] < 0, 'Downtrend', 'Neutral')) df['ROC_Trend'] = np.where(df['ROC'] > 0, 'Uptrend', np.where(df['ROC'] < 0, 'Downtrend', 'Neutral')) def mfi(df): # 典型価格(TP)の計算 df['TP'] = (df['High'] + df['Low'] + df['Adj Close']) / 3 # マネーフロー(Raw Money Flow)の計算 df['Raw Money Flow'] = df['TP'] * df['Volume'] # ポジティブマネーフローとネガティブマネーフローの計算 df['Positive Money Flow'] = np.where(df['TP'] > df['TP'].shift(1), df['Raw Money Flow'], 0) df['Negative Money Flow'] = np.where(df['TP'] < df['TP'].shift(1), df['Raw Money Flow'], 0) # 14期間の合計 window = 14 df['Positive Money Flow Sum'] = df['Positive Money Flow'].rolling(window=window).sum() df['Negative Money Flow Sum'] = df['Negative Money Flow'].rolling(window=window).sum() # MFIの計算 df['Money Flow Ratio'] = df['Positive Money Flow Sum'] / df['Negative Money Flow Sum'] df['MFI'] = 100 - (100 / (1 + df['Money Flow Ratio'])) # シグナルの判定 df['mfi_Signal'] = np.nan for i in range(1, len(df)): if df['MFI'].iloc[i-1] < 20 and df['MFI'].iloc[i] > df['MFI'].iloc[i-1]: df.at[df.index[i], 'mfi_Signal'] = 'Buy' elif df['MFI'].iloc[i-1] > 80 and df['MFI'].iloc[i] < df['MFI'].iloc[i-1]: df.at[df.index[i], 'mfi_Signal'] = 'Sell' def cci(df): # 典型価格(TP)の計算 df['TP'] = (df['High'] + df['Low'] + df['Adj Close']) / 3 # 単純移動平均(SMA)の計算 window = 20 df['cci_SMA'] = df['TP'].rolling(window=window).mean() # 偏差(Mean Deviation)の計算 df['Mean Deviation'] = df['TP'].rolling(window=window).apply(lambda x: np.mean(np.abs(x - x.mean())), raw=True) # CCIの計算 df['CCI'] = (df['TP'] - df['cci_SMA']) / (0.015 * df['Mean Deviation']) # シグナルの判定 df['cci_Signal'] = np.nan for i in range(1, len(df)): if df['CCI'].iloc[i-1] < -100 and df['CCI'].iloc[i] > df['CCI'].iloc[i-1]: df.at[df.index[i], 'cci_Signal'] = 'Buy' elif df['CCI'].iloc[i-1] > 100 and df['CCI'].iloc[i] < df['CCI'].iloc[i-1]: df.at[df.index[i], 'cci_Signal'] = 'Sell' def gap(df): # ギャップアップとギャップダウンの計算 df['Previous Close'] = df['Adj Close'].shift(1) df['Gap'] = df['Open'] - df['Previous Close'] df['Gap Type'] = np.where(df['Gap'] > 0, 'Gap Up', np.where(df['Gap'] < 0, 'Gap Down', 'No Gap')) def hv(df): # ヒストリカル・ボラティリティの計算 window = 20 # リターンの計算 df['Return'] = np.log(df['Adj Close'] / df['Adj Close'].shift(1)) # 標準偏差の計算 df['HV'] = df['Return'].rolling(window=window).std() * np.sqrt(252) # df['RCI'] = df['Adj Close'].rolling(window=window).apply(calculate_rci, raw=False) # シグナルの判定 df['hv_Signal'] = np.nan for i in range(1, len(df)): if df['RCI'].iloc[i-1] < -80 and df['RCI'].iloc[i] > df['RCI'].iloc[i-1]: df.at[df.index[i], 'hv_Signal'] = 'Buy' elif df['RCI'].iloc[i-1] > 80 and df['RCI'].iloc[i] < df['RCI'].iloc[i-1]: df.at[df.index[i], 'hv_Signal'] = 'Sell' 次回は予測をしていこうと思います。 ...

2024年7月2日

短期売買と分析力が向上しそうな株価予測をだらだらとやる part5

前回のあらすじ オシレータ系指標とその他の指標について確認しました。 今回は実際にコードに落とし込んで、グラフで見てみようと思います。 作成したコード 今回はとりあえずトレンド系指標の説明変数を見てみたいと思います。クラスかはまだやってないので、いずれやっておきます。 import pandas as pd import numpy as np import matplotlib.pyplot as plt import os out_fol = "./stock_data/" import glob stock_list = glob.glob(out_fol + "*.csv") def moveing_average(df): # 単純移動平均線(SMA)の計算 df['SMA'] = df['Adj Close'].rolling(window=20).mean() # 指数平滑移動平均線(EMA)の計算 df['EMA'] = df['Adj Close'].ewm(span=20, adjust=False).mean() # グラフのプロット plt.figure(figsize=(14, 7)) plt.plot(df['Adj Close'], label='Close Price', color='black') plt.plot(df['SMA'], label='20-Day SMA', color='blue') plt.plot(df['EMA'], label='20-Day EMA', color='red') plt.title('Stock Price with 20-Day SMA and 20-Day EMA') plt.xlabel('Date') plt.ylabel('Price') plt.legend() plt.grid(True) plt.show() def macd(df): # 短期EMA(12日)の計算 short_ema = df['Adj Close'].ewm(span=12, adjust=False).mean() # 長期EMA(26日)の計算 long_ema = df['Adj Close'].ewm(span=26, adjust=False).mean() # MACDラインの計算 df['MACD'] = short_ema - long_ema # シグナルラインの計算(9日間のMACDのEMA) df['Signal_Line'] = df['MACD'].ewm(span=9, adjust=False).mean() # MACDヒストグラムの計算 df['MACD_Histogram'] = df['MACD'] - df['Signal_Line'] # グラフのプロット plt.figure(figsize=(14, 7)) # 終値のプロット plt.subplot(2, 1, 1) plt.plot(df['Close'], label='Close Price', color='black') plt.title('Stock Price and MACD') plt.xlabel('Date') plt.ylabel('Price') plt.legend() # MACDとシグナルラインのプロット plt.subplot(2, 1, 2) plt.plot(df['MACD'], label='MACD', color='blue') plt.plot(df['Signal_Line'], label='Signal Line', color='red') plt.bar(df.index, df['MACD_Histogram'], label='MACD Histogram', color='gray') plt.xlabel('Date') plt.ylabel('Value') plt.legend() plt.tight_layout() plt.show() def bollinger_bands(df): # 中央バンド(20日間の単純移動平均線)の計算 df['Middle_Band'] = df['Adj Close'].rolling(window=20).mean() # 標準偏差の計算 df['STD'] = df['Adj Close'].rolling(window=20).std() # 上部バンドの計算 df['Upper_Band'] = df['Middle_Band'] + (2 * df['STD']) # 下部バンドの計算 df['Lower_Band'] = df['Middle_Band'] - (2 * df['STD']) # 過熱感の判断 df['bands_buy_flg'] = df['Adj Close'] > df['Lower_Band'] df['bands_sell_flg'] = df['Adj Close'] < df['Upper_Band'] # グラフのプロット plt.figure(figsize=(14, 7)) plt.plot(df['Adj Close'], label='Close Price', color='black') plt.plot(df['Middle_Band'], label='Middle Band (SMA 20)', color='blue') plt.plot(df['Upper_Band'], label='Upper Band (Middle + 2*STD)', color='red') plt.plot(df['Lower_Band'], label='Lower Band (Middle - 2*STD)', color='green') plt.fill_between(df.index, df['Upper_Band'], df['Lower_Band'], color='grey', alpha=0.1) plt.scatter(df.index[df['bands_buy_flg']], df['Adj Close'][df['bands_buy_flg']], label='bands_buy_flg', color='red', marker='o') plt.scatter(df.index[df['bands_sell_flg']], df['Adj Close'][df['bands_sell_flg']], label='bands_sell_flg', color='green', marker='o') plt.title('Bollinger Bands with bands_buy_flg and bands_sell_flg Signals') plt.xlabel('Date') plt.ylabel('Price') plt.legend() plt.grid(True) plt.show() def ichimoku_kinko_hyo(df): # 転換線(過去9日間の最高値と最安値の平均値) df['Tenkan_sen'] = (df['High'].rolling(window=9).max() + df['Low'].rolling(window=9).min()) / 2 # 基準線(過去26日間の最高値と最安値の平均値) df['Kijun_sen'] = (df['High'].rolling(window=26).max() + df['Low'].rolling(window=26).min()) / 2 # 先行スパン1(転換線と基準線の平均値を26日先にプロット) df['Senkou_Span_A'] = ((df['Tenkan_sen'] + df['Kijun_sen']) / 2).shift(26) # 先行スパン2(過去52日間の最高値と最安値の平均値を26日先にプロット) df['Senkou_Span_B'] = ((df['High'].rolling(window=52).max() + df['Low'].rolling(window=52).min()) / 2).shift(26) # 遅行スパン(現在の終値を26日遅らせてプロット) df['Chikou_Span'] = df['Adj Close'].shift(-26) # 雲の上・下の判定とシグナル df['Signal'] = np.where(df['Tenkan_sen'] > df['Kijun_sen'], 'Buy', 'Sell') df['Trend'] = np.where(df['Adj Close'] > df[['Senkou_Span_A', 'Senkou_Span_B']].max(axis=1), 'Uptrend', np.where(df['Adj Close'] < df[['Senkou_Span_A', 'Senkou_Span_B']].min(axis=1), 'Downtrend', 'Neutral')) # グラフのプロット plt.figure(figsize=(14, 7)) plt.plot(df['Adj Close'], label='Close Price', color='black') plt.plot(df['Tenkan_sen'], label='Tenkan-sen (Conversion Line)', color='blue') plt.plot(df['Kijun_sen'], label='Kijun-sen (Base Line)', color='red') plt.plot(df['Senkou_Span_A'], label='Senkou Span A (Leading Span 1)', color='green') plt.plot(df['Senkou_Span_B'], label='Senkou Span B (Leading Span 2)', color='orange') plt.plot(df['Chikou_Span'], label='Chikou Span (Lagging Span)', color='purple') # 先行スパンの領域を塗りつぶす plt.fill_between(df.index, df['Senkou_Span_A'], df['Senkou_Span_B'], where=df['Senkou_Span_A'] >= df['Senkou_Span_B'], color='lightgreen', alpha=0.5) plt.fill_between(df.index, df['Senkou_Span_A'], df['Senkou_Span_B'], where=df['Senkou_Span_A'] < df['Senkou_Span_B'], color='lightcoral', alpha=0.5) plt.title('Ichimoku Kinko Hyo (Ichimoku Cloud)') plt.xlabel('Date') plt.ylabel('Price') plt.legend() plt.grid(True) plt.show() # シグナルとトレンドの表示 print(df[['Adj Close', 'Tenkan_sen', 'Kijun_sen', 'Signal', 'Trend']].tail(30)) def directional_movement_index(df): # True Range(TR)の計算 df['TR'] = df[['High', 'Low', 'Adj Close']].apply(lambda x: max(x['High'] - x['Low'], abs(x['High'] - x['Adj Close']), abs(x['Low'] - x['Adj Close'])), axis=1) # +DMと-DMの計算 df['+DM'] = df['High'].diff().apply(lambda x: x if x > 0 else 0) df['-DM'] = df['Low'].diff().apply(lambda x: -x if x < 0 else 0) # 14期間のTR、+DM、-DMの合計 df['TR14'] = df['TR'].rolling(window=14).sum() df['+DM14'] = df['+DM'].rolling(window=14).sum() df['-DM14'] = df['-DM'].rolling(window=14).sum() # +DIと-DIの計算 df['+DI14'] = 100 * (df['+DM14'] / df['TR14']) df['-DI14'] = 100 * (df['-DM14'] / df['TR14']) # DXの計算 df['DX'] = 100 * (abs(df['+DI14'] - df['-DI14']) / (df['+DI14'] + df['-DI14'])) # ADXの計算 df['ADX'] = df['DX'].rolling(window=14).mean() # シグナルとトレンド強度の判定 df['Signal'] = np.where(df['+DI14'] > df['-DI14'], 'Buy', 'Sell') df['Trend_Strength'] = np.where(df['ADX'] >= 25, 'Strong', 'Weak') # ADXのトレンド(前日と比べて上昇または下降を判定) df['ADX_Trend'] = df['ADX'].diff().apply(lambda x: 'Uptrend' if x > 0 else 'Downtrend' if x < 0 else 'No Change') # グラフのプロット plt.figure(figsize=(14, 7)) plt.plot(df['+DI14'], label='+DI (Positive Directional Indicator)', color='green') plt.plot(df['-DI14'], label='-DI (Negative Directional Indicator)', color='red') plt.plot(df['ADX'], label='ADX (Average Directional Index)', color='blue') plt.title('DMI (Directional Movement Index)') plt.xlabel('Date') plt.ylabel('Value') plt.legend() plt.grid(True) plt.show() # 結果の表示 print(df[['+DI14', '-DI14', 'ADX', 'Signal', 'Trend_Strength']].tail(30)) def parabolic(df): # パラボリックSARの計算 df['SAR'] = np.nan df['EP'] = np.nan df['AF'] = np.nan # 初期値設定 initial_trend = 'up' if df['Adj Close'].iloc[1] > df['Adj Close'].iloc[0] else 'down' initial_AF = 0.02 max_AF = 0.2 # 初期SAR、EP、AFの設定 df.at[df.index[1], 'SAR'] = df['Low'].iloc[0] if initial_trend == 'up' else df['High'].iloc[0] df.at[df.index[1], 'EP'] = df['High'].iloc[1] if initial_trend == 'up' else df['Low'].iloc[1] df.at[df.index[1], 'AF'] = initial_AF # パラボリックSARの計算ループ for i in range(2, len(df)): prev_SAR = df['SAR'].iloc[i-1] prev_AF = df['AF'].iloc[i-1] prev_EP = df['EP'].iloc[i-1] trend = 'up' if df['Adj Close'].iloc[i-1] > prev_SAR else 'down' if trend == 'up': SAR = prev_SAR + prev_AF * (prev_EP - prev_SAR) EP = max(prev_EP, df['High'].iloc[i]) AF = min(prev_AF + 0.02, max_AF) if df['High'].iloc[i] > prev_EP else prev_AF else: SAR = prev_SAR - prev_AF * (prev_SAR - prev_EP) EP = min(prev_EP, df['Low'].iloc[i]) AF = min(prev_AF + 0.02, max_AF) if df['Low'].iloc[i] < prev_EP else prev_AF # トレンドの反転 if trend == 'up' and df['Low'].iloc[i] < SAR: SAR = prev_EP EP = df['Low'].iloc[i] AF = initial_AF trend = 'down' elif trend == 'down' and df['High'].iloc[i] > SAR: SAR = prev_EP EP = df['High'].iloc[i] AF = initial_AF trend = 'up' df.at[df.index[i], 'SAR'] = SAR df.at[df.index[i], 'EP'] = EP df.at[df.index[i], 'AF'] = AF # シグナルの判定 df['Signal'] = np.where((df['Adj Close'].shift(1) < df['SAR'].shift(1)) & (df['Adj Close'] > df['SAR']), 'Sell', np.where((df['Adj Close'].shift(1) > df['SAR'].shift(1)) & (df['Adj Close'] < df['SAR']), 'Buy', np.nan)) # グラフのプロット plt.figure(figsize=(14, 7)) plt.plot(df['Adj Close'], label='Close Price', color='black') plt.plot(df['SAR'], label='Parabolic SAR', linestyle='dashed', color='blue') plt.scatter(df[df['Signal'] == 'Buy'].index, df[df['Signal'] == 'Buy']['Adj Close'], marker='^', color='green', label='Buy Signal', s=100) plt.scatter(df[df['Signal'] == 'Sell'].index, df[df['Signal'] == 'Sell']['Adj Close'], marker='v', color='red', label='Sell Signal', s=100) plt.title('Parabolic SAR with Buy and Sell Signals') plt.xlabel('Date') plt.ylabel('Price') plt.legend() plt.grid(True) plt.show() # 結果の表示 print(df[['Adj Close', 'SAR', 'EP', 'AF', 'Signal']].tail(30)) def Envelope(df): # エンベロープの計算 percentage = 0.02 # 2% のエンベロープ df['Upper Envelope'] = df['SMA'] * (1 + percentage) df['Lower Envelope'] = df['SMA'] * (1 - percentage) # シグナルの判定 df['Signal'] = np.where(df['Adj Close'] > df['Upper Envelope'], 'Sell', np.where(df['Adj Close'] < df['Lower Envelope'], 'Buy', np.nan)) # グラフのプロット plt.figure(figsize=(14, 7)) plt.plot(df['Adj Close'], label='Close Price', color='black') plt.plot(df['SMA'], label='20-Day SMA', color='blue') plt.plot(df['Upper Envelope'], label='Upper Envelope (SMA + 2%)', color='green') plt.plot(df['Lower Envelope'], label='Lower Envelope (SMA - 2%)', color='red') plt.scatter(df[df['Signal'] == 'Buy'].index, df[df['Signal'] == 'Buy']['Adj Close'], marker='^', color='green', label='Buy Signal', s=100) plt.scatter(df[df['Signal'] == 'Sell'].index, df[df['Signal'] == 'Sell']['Adj Close'], marker='v', color='red', label='Sell Signal', s=100) plt.title('Envelopes with Buy and Sell Signals') plt.xlabel('Date') plt.ylabel('Price') plt.legend() plt.grid(True) plt.show() # 結果の表示 print(df[['Adj Close', 'SMA', 'Upper Envelope', 'Lower Envelope', 'Signal']].tail(30)) for stock_data in stock_list: # データフレームの作成 df = pd.read_csv(stock_data) df['Date'] = pd.to_datetime(df['Date']) df.set_index('Date', inplace=True) moveing_average(df) macd(df) bollinger_bands(df) ichimoku_kinko_hyo(df) directional_movement_index(df) parabolic(df) Envelope(df) os.system("pause") 実行結果の確認 コードの作成が完了したので実行してグラフを見てみます。実行したデータはAppleの20年分とMcDonald’sの1年分になります。比較してみてみようと思います。 ...

2024年6月25日