技術屋にゃん兵衛のてくてくらぼ

気の向くままソフトについて書いてます。バリバリエンジニアではないのであくまでも初心者目線で。

PythonでMathematicaのManipulate関数ライクな実装をする

PythonでMathematicaのManipulate関数ライクな実装をする

 

Wolfram Mathematicaには「Manipulate」という関数があり、パラメーターを変化させたときに、グラフがどのように変わるかをインタラクティブに表示する機能があります。

こういうものね↓

reference.wolfram.com

 

Pythonでも似たような実装ができるので試してみました。

ipywidgets(Jupyter Widgets)に、「interact」という関数があります。これを使うと、UIコントロールを使ってインタラクティブに数値を変えたり、グラフを変更したりできます。

グラフを書く前に、まずは通常の数式を変化させてみます。

ipywidgetsでは、まず、コントロールしたい機能を定義する必要があります。

いつも通り、Google Colaboratoryを使います。簡便に試すには、やはりこれは便利。

from ipywidgets import interact

 

def func(a, b):

   return a + b

interact(func, a=3, b=5);

実行すると次のようになります。

ipywidgetsでのスライダーの表示

「a」と「b」のスライダーを図のように触ると、計算結果が変わります。

スライダーを動かしたところ

これでわかるのは、「a=3」「b=5」というのはデフォルトの値で、値の範囲を示しているわけではないことがわかります。また、スライドバーのステップも指定していません。

範囲やステップを指定するには「IntSlider」を使います。書き方は

[変数]=widgets.IntSlider(min=xxxxx. max=yyyyy, step=zzzzz, value=xyzxyz)

です。valueのところが最初のコードで使ったデフォルト値です。

では、実際に先ほどのコードを変えてみます。

import ipywidgets as widgets

from ipywidgets import interact

 

def func(a, b):

   return a + b

interact(func, a=widgets.IntSlider(min=-3, max=3, step=1, value=1), b=widgets.IntSlider(min=-5, max=5, step=1, value=0));

「import ipywidgets as widgets」を追加するのをお忘れなく。

実行すると次の通り。

最大値、最小値などを追加

きっちり動きますね。

スライダーを手で動かすのではく、プレイボタンでアニメーションのようにするには、「widgets.Play」を使います。「a」だけを砕石できるようにするには、次のような感じ。

import ipywidgets as widgets

from ipywidgets import interact

 

def func(a, b):

   return a + b

interact(func, a=widgets.Play(min=0, max=10), b=widgets.IntSlider(min=-5, max=5, step=1, value=0));

実行すると、、、

Playでアニメーション機能を追加した(ボタンが見えない)

ボタンが表示されない。。。ブラウザーのせいかと思って、ChromeからEdgeに変えてみても結果は同じ。

4つボタンがあって、左から、「再生」「一時停止」「停止」「繰り返し」のはずなんですが。

Google Colabだからダメなのかもしれないです。

基本は押さえたので、グラフでスライダーを実装します。ボタンがうまく見えないので、見えるようになるまでアニメーションはパスすることにしました。

正弦関数をプロットして、波長を変えられるようにします。

コードは次のような感じ。

「freq」をスライダーで可変にします。

import numpy as np

import matplotlib.pyplot as plt

from ipywidgets import interact

 

def plot_function(freq):

    x = np.linspace(-10, 10, 1000)

    y = np.sin(freq * x)

 

    plt.plot(x, y)

    plt.grid(True)

    plt.show()

 

interact(plot_function, freq=(0, 10, 1))

実行すると次のようになります。

スライダーでグラフを可変にした

「freq」のスライダーを動かすと、グラフの周波数が変わります。

MathematicaのManipulateだと1行なので、Pythonでは少し行数は増えますが、記述パターンを覚えれば十分に使えそうです。

WLJS Notebookを使ってWolfram言語を動かす(3)

WLJS Notebookを使ってWolfram言語を動かす(3)

 

WLJSのページはこちら

jerryi.github.io

 

WLJS Notebookは、Mathematicaでの「Manupulate」関数はありませんが、簡単なスライダーであればできるようです。

 

WLJS Notebookの左のサンプルが並んでいるペインで、「08- Advanced dynamics」>「SliderExample2.wln」を選択すると次のような画面が開きます。

スライダーのサンプル画面

 

ここで、スライダーを動かす(ドラッグして動かすのではなく、クリックしてください)と、下のグラフィックスが変化します。

スライダーで値を変える

ただ、このコードをコピーして、新しいノートブックに貼り付けて実行すると、スライダーに画像が反応しない。

サンプルだとリアルタイムなんですが、コピーをしたものだと、スライダーを動かしたら、下のセルを再評価する必要があるようです。まだ何か違うんだろうなあ。ごめんなさい、すぐに答えが出ないです。

 

スライダーを2つにした時も試してみました。

スライダー2つも可能

 

動きました。

ただ、評価の時に「JS Console」で、「method destroyが定義されていないよ」と出てきます。おそらくバグっぽい。スライダーを動かして、グラフを再描画するときに出る感じ。

 

いろいろ試していると、結構アラートが出たり、エンジンとの接続が切れたり、少し不安定かな。

 

どんどんアップデートされているので、いろいろと改善されることを期待しましょう。

WLJS Notebookを使ってWolfram言語を動かす(2)

WLJS Notebookを使ってWolfram言語を動かす(2)

 

WLJSのページはこちら

jerryi.github.io

 

今回は「Wolfram言語」とタイトルにはありますが、あまり関係がないかもしれません。

 

前回、WLJS Notebookで、関数のグラフを表示しました。Wolfram言語では、凡例などのコンロトロールがいまいちだということを書きました(これはあくまで、知識不足であるだけなのかもしれません)。

 

WLJS Notebookでもう一つグラフを書く方法があります。こちらのほうが表現力が高いのですが、Wolfram言語ではなく、Plotlyを使ってJavaScriptで処理するというものです。

 

比較のため、まずはおさらいで、Wolfram言語の「Plot」関数を使ったものです。

Plot[Sin[x], {x, 0, 6 Pi}]

Wolfram言語の「Plot」関数で描いたもの

 

次にPlotlyで同じものを書きます。

Plotly[Sin[x], {x, 0, 6 Pi}]

「Plotly」を使って描いたもの

 

軸の位置もいいですすし、マウスポインターを重ねると値も表示されます。

 

前回に使った3つのSinグラフも同じように書けます。まずは、Wolfram言語で再現。

Plot[{Sin[x], Sin[2 x], Sin[3 x]}, {x, 0, 2 Pi}]

 

で、Plotlyを使うと…

 

軸もいいし、凡例も表示されます。

後ろでWolfram Engineとやり取りもしていないようなので、表示が早い。

 

数式処理はWolfram言語でWolfram Engineに処理をさせ、グラフの描画にはPlotlyを使うのがよさそう。

 

となると、混在はできるのか、という疑問がわきます。

ということで、次のコードをWLJS Notbookに入れて実行しました。

d = Dt[3 x^2 + 6 x + 5, x]

Plotly[d, {0, 5, x}]

 

きちっと出ます。

 

ただ、細かな設定をすることはできなさそうです。執筆時点(2024年1月初旬)のWLJSのドキュメントでも次のように書かれています。

 

これができると、もっと表現力が上がると思います。期待してます。

RedmineベースのRedmine X を使ってみる(8.WBSでタスクの作成)

RedmineベースのRedmine X を使ってみる(8.WBSでタスクの作成)

 

Redmine XのWebサイトはこちら

redmine-x.com

 

これまで、一番上位の親プロジェクトを定義して、タスク(チケット)を定義してきました

一旦、タスクが全くない状態にして、もう一つの方法でタスクを作ってみます。

それはWBSを使う方法です。

 

Redmine Xには、マインドマップ的にWBSを行う方法があるので、これを使うと視覚的にブレークダウンを行っていくことができます。

 

  1. プロジェクトの上部のメニューで「WBS」を選択します。メインの画面がマインドマップを作成する画面に切り替わります。

    WBSの画面
  2. トップのプロジェクトの項目(ラスベガス現金強奪)を右クリックして、コンテキストメニューの「追加」->「Add child」(子ノードの追加)を選択します。

  3. タスクの一つ、「現地下見」を入力します。

  4. もう一度「ラスベガス現金強奪」を右クリックして、他の子ノードを追加します。

    保存をしない(ノードがグレイ)で、もう一度「Add child」をすると、既存の子ノードの再編集になります。一度保存すると、ノードが黄色になり、「Add child」をすると、別の子ノードが作成できます。

    もし、保存せずに続けて子ノードを作りたい場合は、「Add sibling」(兄弟ノードを追加)を選択すれば、別の子ノードを作成できます。

  5. 作成したノードの定義(トラッカーや優先度など)を変えようと思い、ノードを右クリックすればメニューが出てきたので、編集できできそう。

    ところが、メニューが見えるので一見、できそうなのですが、次のように「フルバージョンでないとこの機能は使えないよ」と言われました。で、右下の「Get Full version」をクリックするとEasy RedmineのWebサイトに飛びます。

    なんだ、この機能はEasy Software社のEasy WBSだったのね。Easy WBSは無料のようなので、入れてみようと次に進みました。

    「Get full version」で、Easy WBSのページに移り、「Download free plugin」をクリックしてダウンロードの手順を進めようとすると、連絡先などを入れなければならなくなり、営業をかけられるのも嫌なので、このコンテキストメニューを使うことは断念しました。

    Easy Softwareのサイトに飛んでしまう
  6. さて、WBSは終わったので、ガントチャートに移ってみます。きちんとタスク(チケット)が定義されていますね。ここから後は、ガントチャートの説明をしたところと同じです。

 

WBSの機能は、タスク(チケット)を視覚的に定義していくことには使えそうですが、それぞれをタスクをこの中でやろうとすると、「営業されるための情報」を入れなければいけないということですね。

Redmine Xからの営業であれば、今使っているから仕方がないとしても、Easy Software社に情報を出すのは避けたいなー、という感じです。

RedmineベースのRedmine X を使ってみる(7.タスク(チケット)の削除)

RedmineベースのRedmine X を使ってみる(7.タスク(チケット)の削除)

 

Redmine XのWebサイトはこちら

redmine-x.com

 

これまで、一番上位の親プロジェクトを定義して、タスク(チケット)を定義してきました

一旦、タスクが全くない状態にして、もう一つの方法でタスクを作ってみます。そのためには、既存のものを削除する必要があるので、次のように消していきます。

 

まずは、大前提として、自分に「チケットの削除」権限が与えられている必要がありますね。

  1. そこで、次のように、プロジェクト内のタスクの一覧を表示します。

    タスク(チケット)の一覧
  2. 削除するタスクの名前をクリックします。

    タスクの情報画面
  3. 右上の3点メニューで「削除」を選びます。

    メニューから削除

残念ながら、複数のタスクを選んで一括削除はできないのは、ベースのRedmineと同じ。

 

簡単ですけど以上です。

Yahoo!ファイナンスで過去の株価を抜き出してみた

Yahoo!ファイナンスで過去の株価を抜き出してみた

 

機械学習の学習用データとして、またグラフの記事を書く際のデータとして、企業の株価を取りたいけど抜き出せる方法はないかな、と少し考えてきました。

 

で、Yahoo!ファイナンスページのHTMLをソースを保存してみると、中に日別/週別の「始値」「高値」「安値」「終値」「出来高」があることがわかりました。

 

これは、下のような画面上のグラフを書くために埋め込まれたもののようです。

で、グラフの下の期間を選択して保存すると、その期間のデータがソース内に埋め込まれています。

Yahoo!ファイナンスの株価グラフ

 

ブラウザの「ソースを表示」を選択して、ソースを表示し、それをテキストエディターなどにコピーします。

 

ソースをずっと下のほうに見ていくと

{"latestHistoryBaseDatetime":"2023-12-26T00:00:00+09:00",
"histories":[{"baseDatetime":"2021-11-29T00:00:00+09:00",
"openPrice":3282,"highPrice":3426,"lowPrice":3250,
"closePrice":3419,"volume":20888100},{"baseDatetime":"
2021-1206T00:00:00+09:00","openPrice":3460,"highPrice":3525,
"lowPrice":3391,"closePrice":3460,"volume":17387400},

というセクションがあります。

 

「2年」で抜き出した場合、90個データがあるので、おそらく週次のデータなのでしょう。「6カ月」でエクスポートすると、日時で取れました。「1年」は週次です。

 

さて、テキストエディターで、このブロックだけを残して、前後をすべて削除します。始まりと終わりはこんな感じ。

{"baseDatetime":"2023-05-30T00:00:00+09:00","openPrice":4942,"highPrice":4955,
"lowPrice":4893,"closePrice":4953,"volume":3231400},

{"baseDatetime":"2023-12-26T00:00:00+09:00","openPrice":5798,"highPrice":5808,
"lowPrice":5758,"closePrice":5783,"volume":1444000}

 

Excelで開いてみると、下のように1行にずらっと並ぶし、各項目にタイトルがついたままです。

そのままExcelで開いてみると

 

データの並びとしては

{"baseDatetime": “日付”, "openPrice":始値, "highPrice":高値,"lowPrice":安値,"closePrice":終値,"volume":出来高}, {"baseDatetime": “日付”, "openPrice":始値, "highPrice":高値,"lowPrice":安値,"closePrice":終値,"volume":出来高}, {}, {}, {}

のような感じです。

プログラムを作れば、データ部の抜出から、CSVの成形まで、一気にできそうです。

これはAIのためのデータの前処理だと考えればいいでしょう。

 

目標のデータ形式は、

baseDatetime, openPrice, highPrice, lowPrice, closePrice, volume
日付, 始値, 高値, 安値, 終値, 出来高
日付, 始値, 高値, 安値, 終値, 出来高
日付, 始値, 高値, 安値, 終値, 出来高

です。

 

すぐにコードを書いて試すには、Google Colaboratoryが便利なので、それを使って処理してみます。

 

  1. 新しいノートブックを作成し、左端のフォルダアイコンをクリックしてファイル管理のペインを出し、そこに先ほどのファイルをアップロードします。

    テキストファイルをGoogle Colaboratoryにアップロード
  2. 次のようなPythonコードを入れて、CSVに成形します。どの文字を捜査しているかをわかりやすくるために、何行かに分けて書いています。

    file_path = '/content/Stock_Price.txt'

    with open(file_path, 'r') as file:
        content = file.read()


    modified_text = content.replace('},', '},\n')
    modified_text = modified_text.replace('{"baseDatetime":"', "")
    modified_text = modified_text.replace('T00:00:00+09:00"', "")
    modified_text = modified_text.replace('"openPrice":', "")
    modified_text = modified_text.replace('"highPrice":', "")
    modified_text = modified_text.replace('"lowPrice":', "")
    modified_text = modified_text.replace('"closePrice":', "")
    modified_text = modified_text.replace('"volume":', "")
    modified_text = modified_text.replace('},', "")
    modified_text = modified_text.replace('}', "")
    modified_text = "baseDatetime, openPrice, highPrice, lowPrice, closePrice, volume\n" + modified_text

    print(modified_text)

     

  3. 次のような出力が返ってきます。

    Pythonの実行結果
  4. この出力をコピーして、テキストエディタに張り付け、csvとして保存します。

    Excelで開くと次のように処理しやすい形になってます。

    整形後のファイルをExcelで開く
  5. 「高値」(C列)をプロットすると次のようになり、Yahoo!ファイナンスに表示されていたグラフと一致していることがわかります(株価は本当は箱ひげ図なんでしょうが…)。

最後に、このCSVをもとのテキストファイルと同じ場所に保存するために、コードの最後に次を追加しておきます。

file_path = '/content/Stock_Price.csv'


with open(file_path, 'w') as file:
    file.write(modified_text)

これで、ファイルもできました。

処理しやすいファイルにすることで、他の会社の株価や、商品価格などとの相関を見たりすることができるようになりました。

RedmineベースのRedmine X を使ってみる(6.スケジュールの定義)

RedmineベースのRedmine X を使ってみる(6.スケジュールの定義)

 

Redmine XのWebサイトはこちら

redmine-x.com

 

タスク(チケット)の定義の時に、スケジュール(開始日と終了日)を決めてもいいのですが、タスクの前後関係のことを考えると、ガントチャート内で作業をすることのほうが多いと思います。

 

今回の現金強奪の場合、実行に移す日です。これは、現金が大量に動く日に実施することになるので、その日を完了日とします。現金が動く日は定期的にあり、スケジュール優先で準備不足になるよりは、それぞれのタスクに必要な時間を考えて積み上げ式で考えることにしました(その日のうちに逃げてしまうため、この日がプロジェクト完了日)。

 

  1. 実行日の前に行うものとしては、「現地下見」「機材調達」「事前の仕込み」「逃走手段確保」です(「その他」は必要に応じて行うタスクとし、前後関係や事前の担当割り当ては行いません)。
    ガントチャート内で、一番時間のかかりそうな「事前の仕込み」のバーの右端にマウスポインターを合わせると「<―>」に変わるので、一旦最初の計画実行日まで、ずるずると右にドラッグします。

    ガントチャートのバーを伸ばす
  2. タスクが長期になる場合、ガントチャートの上にある「Zoom level」で「Week」選んで、ガントチャートの表示の単位を「週」にすると引きやすいと思います。

    ガントチャートの目盛りを「週」にする
  3. 「現地下見」「機材調達」「逃走手段確保」は、「事前の仕込み」期間内で、作業ができる日を定義します。

    一旦、次のようになったとします。

    (ガントチャートは、マウスでドラッグすると、左右に日付を動かすことができます)

  4. 「事前の仕込み」は「当日の行動」に必ず続きます。なので、この2つのタスクを繋ぎます。「事前の仕込み」のバーの右にある「〇」から線を伸ばして「当日の行動」の左の「〇」につなぎます。

    タスク(チケット)間の関連付け
  5. 2つのタスクの関係はどのようなものか(Relation type)を定義する画面になります(執筆時点では、まだ日本語になっていない)。今回は、「Precedes/Follows(先行/後続)」を選択します。「Finish to Start(終了後開始)」「Relates(関連)」も選ぶことができ、「Enter delay」では、前のタスクの終了後、何日で次を始めるかを入力します。

    どのように関連付けるか
  6. 完了したら、次のように繋がりました。

タスクの前後関係を考える時には、「誰がそれをするのか」も重要(時には、タスクが重ならないように、あるいは負荷が集中しないようにする必要もあるので)なんですが、今の状態だとガントチャートに担当者が表示されていない(マウスを重ねると表示はされます)ので、少し不便な気がしました。

各タスク(行)に担当者を表示する機能は今のところなさそうです。要望しておこう。入れてくれるかどうかは知らんけど。