ストックドッグ

KatoTakahiro。金融系の会社で働くSEが株やPython、その他諸々について書いています。サービスも運営してます→http://fmbrain.work

「sudo: pip: コマンドが見つかりません」というエラー

現象

このエラーは、pipコマンド自体をアップデートしていなかったら現れるようです。

#pip単体でのインストールはエラーは出ないが
pip install library

#sudoを組み合わせると、エラーが発生
sudo pip install library

sudo: pip: コマンドが見つかりません

原因

sudoの参照先にpipコマンドがないためため、コマンドが見つからないというエラーメッセージ通りです。

以下のコマンドで異なるパスを参照しようとしていることがわかります。

私はanacondaでpythonを入れているため、このような現象が起きます。

which pip
#/home/username/anaconda3/bin/pip

which sudo
#/usr/bin/sudo

/usr/bin/の中にpipコマンドがあれば、このようなエラーは起きませんが、pipはanacondaのbinにあります。

対処法1

単純明快、pipコマンドをアップグレードする。

この下のどれでもアップグレードできるので、自分の環境に合わせたコマンドを選択する。

pip install -U pip
easy_install pip
conda install pip

pipのインストーラーを直接、サイトからダウンロードしてきても可。

Installation — pip 9.0.1 documentation

ダウンロードしてきたら、ファイルを実行する。

python get-pip.py

ちなみに、自分はこれらのどれでもなく、ubuntuのapt-getで入れたpipを使っているので以下のコマンド。

sudo apt-get install python-pip

対処法2

対処法1で対処できなかった場合です。

sudoの後にanacondaのpipの参照先を指定します。

which pip
#/home/username/anaconda3/bin/pip

sudo /home/username/anaconda3/bin/pip install libname

ちょとナガイ。

環境変数を変えるなり、aliasに登録なりすると便利!

これらのどれかで解決できるはず

問題は、どの入れ方でpipをインストールしたかです。

pipとコマンドをうったときに、参照してる先のpipを指定しないとこのエラーは直りません。

以上、終わり!

pythonでシェルスクリプト実行(カレントディレクトリ取得したり、cdしたり)

pythonシェルスクリプト実行をしたい

import os

os依存のコマンドをこのライブラリで実行することが出来ます。

端末(ubuntu)やターミナル(mac)の上でうつコマンドをpythonのプログラムで書けるなかなか汎用性の高いライブラリです。

例えば...

カレントディレクトリの取得したい!時のpwdコマンドや、

ディレクトリを移動したい!時のcdコマンドなどが、

pythonプログラムを通して、実行できるわけです。

カレントディレクトリを取得する

os.getcwd()
#'/home/user/py3'

こんな感じでカレントディレクトリを取得。

pwdを端末上で打つのと一緒ですね。

ディレクトリの移動をする

os.chdir("/home/user/py3")

""(ダブルコーテーション)内に移動したい先を絶対パスで書きます。

相対パスでも行けるかも。

ただ、相対パスはトラブルの元なのでとりあえず絶対パス推奨。

他にも色々なコマンドを!

>|python
#ディレクトリを作成|
os.system('mkdir test')
|

os.systemは、コーテーション内にシェルスクリプトを書くことで実行が可能です。

コマンドが実行できた場合は、0が返り値となります。

他にも。

>|python
#ファイル作成
os.system('touch test')
|

Pythonで画像処理 〜2枚の画像を重ねてみる〜

pythonのライブラリ、pillowを使って、2つの画像を重ねてみたいと思います。

重ねる画像はこの2つ。

アナログテレビ時代のザザーッって感じのやつ。

微妙にこの2つの画像、違います。

これを重ねてみます。

f:id:doz13189:20170723012946p:plain

f:id:doz13189:20170723013003p:plain


以下が重ねるコードです。

画像のピクセルを配列に入れる関数と画像を重ねる関数の2つを使って、画像を重ねています。

コードと一緒に、コードの動きをコメントで書いています。

#pillowとnumpyをインストール
from PIL import Image
import numpy as np

#画像のピクセルを配列に入れる関数
def pixelGetter(img):
	#画像を開く
	img = Image.open(img)
	
	#画像のサイズ(縦×横)を入れる
	#今回使用する画像は640×480
	size = img.size
	#print(size[0])
	#print(size[1])

	#配列を入れる変数を定義
	img_pixels = []
	for x in range(size[0]):
		for y in range(size[1]):
			#画像の左上から順番にピクセルの情報を取得
			#1ピクセルの情報は(r, g, b, 透過度)
			#この情報をappendで配列に入れている
			img_pixels.append(img.getpixel((x,y)))

	#ピクセル情報が入っている配列をリターン
	return img_pixels

#画像を重ねる関数
def pileUp(pic1, pic2):
	#2枚の画像を開く
	img = Image.open("pic1.png")
	img2 = Image.open("pic2.png")

	#2枚の画像のサイズを入れる
	size = img.size
	size2 = img2.size

	#2枚の画像を重ねるための変数を定義
	#重ねるといっても、実際は2枚の画像から新しい3枚目の画像を作成している
	#そのため、3枚目の画像を入れる変数をここで定義する必要がある
	#サイズは2枚の画像と一緒であるため、640×480を入れる
	new_img = Image.new("RGBA", size)

	#重ねる処理を行う
	#画像を重ねるというのは、中の処理は1つ1つのピクセル同士を足し合わせるということ
	#赤い透明の下敷きを2枚重ねると、濃い赤になる原理と同じ
	#そのため、2枚の同じ位置同士のピクセルの(r, g, b)を足し合わせている
	i = 0
	for x in range(size[0]):
		for y in range(size[1]):
			r = pic1[i][0] + pic2[i][0]
			g = pic1[i][1] + pic2[i][1]
			b = pic1[i][2] + pic2[i][2]

			#ピクセル情報の入った配列では、画像を表示する形式に合わない
			#そのため、putpixelで画像表示の形式に変換
			new_img.putpixel((x, y), (r, g, b, 255))
			i += 1

	#リターンで重ねた画像を表示
	return new_img.show()


pic1 = pixelGetter("pic1.png")
pic2 = pixelGetter("pic2.png")
pileUp(pic1, pic2)

結果的に、重ねると...

f:id:doz13189:20170723013216p:plain

重ねるとちょっとした文字がでてきましたね。(出てきた文字に特に意味はありません)

まとめ

pythonって色々なことができるんだなぁと実感しました。

たまにいつもと違うコードを書くのも楽しいですね。

以上終わり。

ROT13をPythonで実装してみる

ROT13って何?

ROT13 または ROT-13、rot13 は単換字式暗号(シーザー暗号)の一つである。アルファベットを一文字毎に13文字後のアルファベットに置き換える。Aは Nに、 B は O に置き換えられ、以下同様である。英語の "Rotate by 13 places" の略。ネットワーク上のやりとり(電子掲示板、ネットニューズ、フォーラム等)で冗談の落ち、パズルの解法、ネタばれ情報、不快表現等を隠すのに用いられるアルゴリズムである。実際には暗号というほどのものではないが、ちょっと見に読んでしまうという事態は避けられる。雑誌などでクイズの正解を上下逆さまに印刷するが、それと似たようなものである。

ROT13 - Wikipedia

実装手順

この文字はROT13で暗号化された文字です。

pboby vf sbffvy.

文字にそのまま13は足せないので、一度この文字列をASCIIの数値に変換します。

以下、ASCIIコードの数値と文字の対応表のURL。

文字と数値 | サルにも分かるRSA暗号

112 98 111 98 121 32 118 102 32 115 98 102 102 118 121 46

ASCIIの数値に変換するとこうなります。


文字コードに変換してから、13を足すか引くかの条件を分岐するので、ASCIIの文字コードに変換した時

  • 65〜77であれば、プラス13
  • 78〜90であれば、マイナス13
  • 97〜109であれば、プラス13
  • 110〜123であれば、マイナス13

これで、A〜Z、a〜zの対応付けすることができます。


以下、簡単な対応表です。

A - M 65 - 77
N - Z 78 - 90
a - m 97 - 109
n - z 110 - 123

実装してみる

contents = "pboby vf sbffvy."
process = ""
for script in contents:
	num = ord(script)

	#space or period
	if num == 32 or num == 46:
		ascii_script = chr(num)

	#A - M
	elif num >= 65 and num <= 77:
		ascii_script = chr(num + 13)

	#N - Z
	elif num >= 78 and num <= 90:
		ascii_script = chr(num - 13)

	#a - m
	elif num >= 97 and num <= 109:
		ascii_script = chr(num + 13)

	#n - z
	elif num >= 110 and num <= 123:
		ascii_script = chr(num - 13)

	process += ascii_script

print(process)

このプログラムをじっこうした結果

cobol is fossil.

こうなります。

まとめ

最近は新人研修に勤しむ毎日です。

しかも、なななんとcobolの研修なので楽しくて楽しくてたまりません汗

以上終わり。

seleniumで自動売買 〜SBI証券から自動で株を買ってみる〜

自動売買ってどうやってやるの?

アルゴリズムトレードが昨今流行りではありますが。

残念ながら日本の証券会社は一般向けに株式売買のAPIは公開されていません。

そのため、APIを通してのアルゴリズムによる株の自動売買は現状できません。

FXやビットコインAPIが公開されているので、アルゴリズムで自動売買を行っている人が多いようですが、株式で自動売買をやっている人があまりいないのはここらへんの理由かと思います。

(高頻度取引は東京証券取引所に登録すれば可能なようですが、調べてもあまり情報がでてきません、個人では行えず法人のみっぽいです)

最近、銀行の取引をAPI化して業務提携をする動きが盛んになってきていますが、証券会社が売買等のシステムをAPI化する話はあまり聞きません。

こういった話は国主導で進めるので、明日急にAPI公開なんてことにはならないので、株式売買のAPI公開はいったん諦めましょう。


では、どうやるか。

どうやらseleniumというウェブのUI自動テストツールが使えそうです。

seleniumはクリックや文字入力をプログラムを通して、自動で行えることができるライブラリです。

もともとはシステムのテストを自動化する目的で発展してきたようですが、これを使ってウェブを操作することもできます。

つまり、SBI証券にログインして、株を売買する動きもseleniumで再現できるということです。

seleniumの簡単な使い方の記事

前にyoutubeで「yui」と検索するコードをseleniumで書きました。

doz13189.hatenablog.com

これをちょっと変えるだけで、SBI証券にログインして株を売買するってのはできそうです。

SBI証券にログインして株を買ってみる

import unittest
from selenium import webdriver
from selenium.webdriver.common.keys import Keys


class PythonOrgSearch(unittest.TestCase):


	def setUp(self):
		
		self.driver = webdriver.Chrome("/home/ubuntu/robo/chromedriver")


	def test_serch_in_python_org(self, signal=1):
		driver = self.driver

		#SBI証券のHP
		driver.get("https://www.sbisec.co.jp/ETGate")

		#SBI証券のログインID
		driver.find_element_by_name("user_id").send_keys("login_id")

		#SBI証券のログインパスワード
		driver.find_element_by_name("user_password").send_keys("login_password")
		driver.find_element_by_name("ACT_login").click()

		driver.find_element_by_xpath('//div[@id="link02M"]/ul/li[2]').click()

		if signal == 1:
			PythonOrgSearch.buy(self)

		elif signal == 0:
			PythonOrgSearch.sell(self)


	def tearDown(self):
		self.driver.close()


	def buy(self):
		print("buy")

		driver = self.driver

		#現物買にチェック
		driver.find_element_by_name("trade_kbn").click()
		
		#銘柄コードを入力
		driver.find_element_by_name("stock_sec_code").send_keys(1305)
		
		#売買株数を入力
		driver.find_element_by_name("input_quantity").send_keys(100)
		
		#価格指定
		driver.find_element_by_xpath('//td[@id="gsn1"]/input').click()

		#預かり区分を指定
		driver.find_element_by_name("hitokutei_trade_kbn").click()
		
		#取引パスワードを入力
		driver.find_element_by_name("trade_pwd").send_keys("trade_password")

		#注文確認画面をクリック
		driver.find_element_by_name("ACT_estimate").click()

		#注文発注
		driver.find_element_by_name("ACT_place").click()


	def sell(self):
		print("sell")

if __name__ == "__main__":
    unittest.main()

HTMLの構造上、find_element_by_nameで要素を取得できない部分はxpathを使いました。

成行か指値か、を選択するところがまさにそれで、仕方がなくxpathを使っています。

SBI証券はHPにJaveScriptを使用していないので、selenium単体で全ての操作を完結させることができました。

selenium自体の使い方はシンプルなので、コードを書くと言ってもHTMLの構造を読むのがメインでした。

このコードを実行すると...

銘柄コード1305の株を100株、成行で買います。

東京証券取引所が開いている時間に実行すると、本当に約定してしまうので夜に実行しましたが、しっかりと注文できました。

seleniumゆえの欠点

上記のコードは単体テストのライブラリをインポートして、全ての操作の開始から終了までの時間を計測しています。

結果的に全ての操作を終えるのに、22秒程度かかります。

インターネットの接続状況によってはもう少しかかる場合もあります。

つまり、注文に時間がかかりすぎです。

1日1回や2回程度ならこの程度のスピードで十分ですが、頻度を上げるには少し実行速度が遅いように思います。

そのため、売買まで20〜30秒程度なら許容できるアルゴリズム取引戦略が必要になります。

デイトレをするには心もとないので、やはりスイングトレードかなぁなんて思っています。


以上終わり。

seleniumの環境構築と簡単な使い方

今は日曜日の夜2時

早く寝ないと!!

明日は仕事なんです。

急いで書くのでぶっきらぼうな今日は文章になるかもです。

何とかブログだけ書いてさっさと寝ます。

環境構築

pipでインストール可能です。

pip install selenium

seleniumAPIを通じてブラウザを使用するため、seleniumとは別にブラウザ用のドライバーをインストールする必要があります。

sites.google.com

SafariFirefoxChrome、Edge、どれでも好きなブラウザのドライバーの圧縮ファイルをHPからダウンロードでき、私はChromeを選択しました。

ダウンロードした圧縮ファイルを解凍するとChromedriverというファイルが現れます。

これをseleniumを使用するファイルと同じフォルダに入れておきます。


公式HPにはPATHを通すと書いてあったが、そこは本人の自由。

私は面倒だったので、そのままコードの中にChromedriverの位置を書きました。


ここらへんの環境構築にちょっと苦労しました。

Youtubeで「YUI」と検索する操作をseleniumを使ってやってみる

#unittestは単体テスト用のライブラリ。
#動作の開始から終了までの時間を計測してくれるので、なんとなく使用。
import unittest

from selenium import webdriver
from selenium.webdriver.common.keys import Keys


class PythonOrgSearch(unittest.TestCase):

	def setUp(self):
		#pwdでカレントディレクトリを確認。
		#カレントディレクトリの場所をそのまま記述。
		#seleniumを実行するファイルとChromedriverを同じ場所に格納が楽。
		self.driver = webdriver.Chrome("/home/ubuntu/serv/robo/chromedriver")


	def test_serch_in_python_org(self):
		driver = self.driver
		#youtubeのURL
		#driverの中にはサイトの構造がHTMLとして格納されている。
		driver.get("https://www.youtube.com/")

		#youtubeの検索バーはid="masthead-search-term"
		#find_element_by_idで検索バーのidを取得してくる
		elem = driver.find_element_by_id("masthead-search-term")

		#yuiと検索
		elem.send_keys("yui", Keys.RETURN)

	def tearDown(self):
		self.driver.close()


if __name__ == "__main__":
    unittest.main()


ちなみに、youtubeのサイト構造の画像。
id="masthead-search-term"が検索バーであることがわかります。

f:id:doz13189:20170424023003p:plain

クリックもできるselenium

クリックを自動で行いときは.click()で可能。

方法はだいたいさっきと同じで、HTMLからクリックしたい要素のidを探して.click()をつけたします。

driver.find_element_by_id("about").click()

公式サイトを見るとドラッグ・アンド・ドロップもできるみたいだが、どの場面でドラッグ・アンド・ドロップを使うのかは私には思いつかない...

id要素以外の見つけ方

  • find_element_by_id
  • find_element_by_name
  • find_element_by_xpath
  • find_element_by_link_text
  • find_element_by_partial_link_text
  • find_element_by_tag_name
  • find_element_by_class_name
  • find_element_by_css_selector

案外たくさんある...

個人的にはclass_nameとidがあれば90%の作業はすむと思っています。

けっこう簡単だったselenium

思いの外使いやすかったです。

使い方自体もシンプル。

そして、汎用性抜群。

もうしばらく触ってみます。

herokuでのスケジュール管理にAPSchedulerを使ってみる

目次

herokuで定期的にファイルを実行したいとき何を使っていますか?

cron?

heroku scheduler?

APScheduler?

cron...?

DBの更新、データの取得、バックアップの保存などのスケジュールの管理はモダンなWebアプリには必須機能です。

ubuntuのデフォルトでインストールされているcronはあらゆるスケジューリングが可能で、上記のほとんどのことはcronによって達成することが出来ます。

ですが、cronはサーバー上で動作することもあり、Webアプリのテストをローカル環境で行うことを考えると、もっと高いレイヤーのアプリケーションのインスタンスで動作するほうが勝手がいいです。

heroku scheduler...?

herokuにはスケジュール管理のためのファンタスティックなアドオンが用意されています。

このheroku schedulerはシンプルなタスクを10分、1時間、一日、複数の間隔での実行が可能です。

しかし、5分や37分など中途半端な時間での実行は難しいです。

cronよりもheroku schedulerよりAPSchedulerが良い

アプリケーションのインスタンスで動作し、かつ、中途半端な時間でも簡単にスケジュールの管理が可能なのが、APSchedulerです。

これはPython製のライブラリなので、私のようにwebアプリを全てpythonで完結させたい人たちにはもってこいです。

heroku上でAPSchedulerを使ってみる

ということで、1分おきに現在時刻をDBにインサートするプログラムを書いてみます。

最終的な出力はこうなります。

herokuのログを見ると、1分おきにDBを更新していることがわかります。

f:id:doz13189:20170410001021p:plain

用意するもの

herokuでアプリを運用するために必要なファイルは以下です。

#適当に用意してください
runtime.txt
requirements.txt

#以下は今から作成します
Procfile
gettime.py
time.db
timeclock.py

スタート。

#screamtimeという名前のアプリを作ります
heroku create screamtime

次に、gettime.pyを作成します。

import sqlite3
import pandas as pd
import datetime


#現在時刻を取得する
now = datetime.datetime.today()
hour = now.hour
minute = now.minute

#DataFrame形式にぶち込む
#普通はSQL文書いてインサートすると思いますが、
#私がDataFrame形式に慣れているので、こちらを使用していますが、各自なれた方法でお願いします
time_df = pd.DataFrame({"Hour" : [hour], "Minute" : [minute]})


#db作成
dbname = "time.db"

#dbコネクト
conn = sqlite3.connect(dbname)
c = conn.cursor()

#dbのnameをtime_dfとし、読み込んだcsvファイルをsqlに書き込む
#if_existsでもしすでにtime_dfが存在していても、置き換えるように指示
time_df.to_sql("times", conn, if_exists="replace")

#作成したdbを見てみる
select_sql = 'select * from times'
for row in c.execute(select_sql):
    print(row)

conn.close()

これをgettime.pyという名前で保存します。

次は、今作成したgettime.pyをAPSchedulerで定期的に実行させるコードを書きます。

from apscheduler.schedulers.blocking import BlockingScheduler
import os

sched = BlockingScheduler()

#間隔は1分ごとにしています
#minutesではなくてhourに変更したら、時間での指定も可能です
@sched.scheduled_job('interval', minutes=1)
def timed_job():
	print("Let's start")
	os.system("python gettime.py")


sched.start()

これをtimeclock.pyという名前で保存します。


最後にProcfileを作成します。

clock: python timeclock.py

これで、herokuにclockのファイルであるということを宣言します。

ファイルが全て揃ったので、あとはherokuに上げるだけです。

念の為、herokuに上げるまでのgitでの手順を載せておきます。

git init
git add .
git commit -m "first commit"
git push heroku master

エラーなく行けば、これでherokuには「1分おきに現在時刻をDBにインサートするプログラム」がアップロードされました。

以下でherokuにclockをスケールします。

heroku ps:scale clock=1

上手くスケールされたことを確認して。

heroku ps
|<

数分待ってからherokuのログを見てみます。

>||
heroku logs

f:id:doz13189:20170410001021p:plain

以上で「1分おきに現在時刻をDBにインサートするプログラム」が完成しました。

まとめ

APSchedulerはとても簡単にスケジュールの管理が行うことができます。

コードもpythonで書くことができるので、使い勝手がとても良いです。

cronよりもheroku schedulerよりもAPSchedulerが良いんじゃあないでしょうか!?