エンジニアの頭の中

知識と技術で「お金稼ぎの自動化」を実現するため、日々奮闘するエンジニアのブログです。

PythonによるLiquid by Quoine のプライベートAPIの認証方法

f:id:mitsu3204:20181025190055j:plain

先日、Liquid by Quoine(旧Quoinex)のプライベートAPIを呼び出す際の認証処理をGoで書きましたが、同様の処理をPythonでも書いたので、コードを公開しておきます。

www.hacky.xyz

Pythonで書いた理由

ccxtを使用していたので、APIの認証処理を意識する必要はなかったのですが、ボットを改良する過程で細かいエラーハンドリングを行う必要が出てきたからです。

ccxtだと、API実行時に何らかの例外が発生すると、Pythonの標準の例外クラスをccxt独自の例外クラスでラップして投げてきます。 それでもやりたきことの実現は可能なのですが、実装の効率・保守性等を考えると、あまりよろしくないため、Quoineのボットではccxtの使用をやめて、自前のコードでAPIを呼び出すことにしました。

PyJWTのインストール

以前、Goで書いた際の記事にも書きましたが、QuoineのAPI認証はJWTを使用します。

事前準備として、PythonでJWTを扱うためのライブラリがあるので、これをインストールします。

$ pip install PyJWT

PythonによるLiquid by QuoineのプライベートAPI認証を行う実装

例として、自分の取引履歴を取得する以下のプライベートAPIを呼び出してみます。

GET /executions/me?product_id=:product_id

署名生成関数の作成

プライベートAPIを呼び出す際は、HTTPリクエストのヘッダーに「X-Quoine-Auth」の名前でHTTPリクエストの署名を付与します。

署名を生成する関数を作成します。

import time
import jwt

def sign(path: str, api_key: str, api_secret: str) -> bytes:
    payload = {
        'path': path,
        'nonce': str(int(time.time())),
        'token_id': api_key
    }
    return jwt.encode(payload, api_secret, algorithm='HS256')
  • path

APIのURLに含まれるパスの部分の文字列です。例えばhttps://api.liquid.com/fiat_accountsというAPIを呼び出すのであれば、/fiat_accountsという文字列を指定します。

  • api_key

自分のAPIのキーを指定します。

  • api_secret

自分のAPIシークレットを指定します。

認証用のHTTPヘッダの作成

HTTPヘッダにX-Quoine-Authの名前でsign関数で生成した署名をセットします。

Content-TypeX-Quoine-API-Versionは、呼び出し対象のAPIがプライベートかどうかに関わらずセットするものです。

HTTPヘッダのUser-Agentを設定しているのは、urllibのデフォルトのHTTPヘッダだと、APIサーバから403(Forbidden)のステータスコードが返されたからです。回避するためUser-AgentFirefoxのものに偽装しています。

# 取引履歴を取得するAPIのパス。product_id=5というのはBTC/JPYのこと
path = '/executions/me?product_id=5'

# 署名付きヘッダーを作成
heaers = {
    'X-Quoine-Auth': sign(path, '<APIキー>', '<APIシークレット>'),
    'X-Quoine-API-Version': '2',
    'Content-Type': 'application/json',
    'User-Agent': "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:47.0) Gecko/20100101 Firefox/47.0"
}

プライベートAPIの実行

作成したpathheadersを使ってHTTPリクエストオブジェクトを作成し、Liquid by QuoineのプライベートAPIを呼び出します。

HTTPリクエストの送信にはccxtを使用しないため、Pythonの標準ライブラリであるurllibを使います。

import urllib.request

# HTTPリクエストを作成
req = urllib.request.Request(url='https://api.liquid.com' + path, headers=headers, method='GET')

# HTTPリクエストを送信
res = urllib.request.urlopen(req)

# HTTPレスポンスを読み取る
result = res.read().decode('utf-8')

最終的にAPIの呼び出し結果を受け取ったresultという変数には、以下のようなJSON形式の文字列が格納されます。

{
 "current_page": 1,
 "total_pages": 10000,
 "models": [
  {
   "id": xxxxxxx,
   "quantity": "0.4",
   "price": "718848.0",
   "taker_side": "sell",
   "created_at": 1540458553,
   "my_side": "buy"
  },

作って覚える!Pythonista 3を使ったPythonプログラミングのやり方

iOSPythonプログラミングができるPythonista 3 のアプリですが、Pythonista 3のモジュールの利用方法の調査のために、Pythonista 3 を使ってライフゲーム(Conway's Game Of Life)を書いてみました。

Pythonista 3 / omz:software

f:id:mitsu3204:20181016133630j:plain

Pythonista 3もPythonとしての書き方は、通常のPythonと変わりませんが、アニメーションの描画やUIの操作については、Pythonista 3 の独自モジュールの使い方を把握しておかなければなりません。

私は、Pythonista 3に同梱されているサンプルソースと、Pythonista 3の公式ドキュメントを確認しながらコードを書きました。

Pythonista 3とは

iOSバイス上でPythonプログラミングができるアプリです。

www.hacky.xyz

ライフゲームとは

ライフゲームとは、生命の誕生と死滅のシミュレーションプログラムです。

セル(細胞)の状態の変化を眺めて楽しむだけのもので、ゲームと名付けられていますが、ゲーム感はありません。

私がライフゲーム好きなのと、小さい規模で作ることができ、お試しのプログラムとしてはちょうど良いので、題材として選択しました。

ライフゲームについては、過去記事もあるので、興味あるかたはどうぞご覧ください。

www.hacky.xyz

www.hacky.xyz

 実装

大した実装量ではなく、1ファイルに収まる程度です。

ファイルを新規作成する

まずは、以下の手順に従ってファイルを新規作成します。

  1. Pythonista 3 アプリを起動します。

  2. 「New File」をタップして、ファイル新規作成画面を開きます。

  3. テンプレートの一覧の中から「Game / Animation」をタップします。

f:id:mitsu3204:20181017213002j:plain

  1. 画面丈夫のテキストフィールドにファイル名を入力します。名前は何でも良いです。

f:id:mitsu3204:20181017213039j:plain

  1. 名前を入力したら、Createボタンをタップします。

これで新規ファイルが作成されました。「Game / Animation」のテンプレートを使用したソースコードの初期状態は以下のようになっています。

f:id:mitsu3204:20181017213052j:plain

画面右上の「>」ボタンをタップすると、このPythonコードを実行できます。まだ何も具体的な処理を書いていないため、実行すると以下のようにグレーの画面が表示されるだけです。

f:id:mitsu3204:20181017213146j:plain

実行したプログラムは、右上の×ボタンをタップすると終了することができます。

初期化処理を作成

最初からテンプレートの内容として含まれているクラス名や、メイン関数などは変更する必要はありません。メソッドの中身を書き足していくのと、いくつかメソッドを追加したら完成です。

まず、空実装状態のsetupメソッドの中身を書き加えて行きます。

描画する背景の色(background_color)、セルの色(cell_color)、描画するセルの大きさ(cell_size)をインスタンスのメンバとして設定します。色の指定は、blackgreenなどのように、定義済みの色の名前でも良いですし、コードで指定することも可能です。

セルを描画する行と列の数は、セルの大きさと画面の大きさに基づいて、動的に計算します。

最後にinit_cellsメソッド(テンプレートに含まれていたものではなく自分で実装するメソッド)を呼び出して、セルの初期状態を作ります。

def setup(self):
        
    # 背景の色
    self.background_color = 'black'
        
    # セルの色
    self.cell_color = 'green'
        
    # 一つのセルの大きさ
    self.cell_size = 12
        
    # 画面のサイズとセルの大きさをから、行と列の数を計算する
    self.row_num = int(self.size.h / self.cell_size)
    self.col_num = int(self.size.w / self.cell_size)
        
    # セルを初期化
    self.cells = self.init_cells()

init_cellsメソッドの中身は、以下のとおりです。

各セルの生死の状態は、二次元の配列で管理します。それぞれのセルは「生(0)」か「死(1)」のどちらかの状態を持ちます。

初期状態は、各セルごとに擬似乱数を使って決定します。ループの中で実行しているrandom.randint(0, 1)は、0か1かどちらかの数値をランダムに返します。0なら「死」で1なら「生」を表します。

def init_cells(self):
    """全てのセルを初期化します。

  各セルの状態(ON or OFF)は、ランダムに決定します。
  """
    rows = []
    for row in range(self.row_num):
        cols = []
        for col in range(self.col_num):
            cols.append(random.randint(0, 1))
        rows.append(cols)
    return rows

セルの描画処理を実装

次は描画状態の更新処理を書きます。

このupdateメソッドは、テンプレートに含まれているSceneクラスから継承しているメソッドです。

updateメソッドは、MySceneクラスの外側から定期的に自動で呼び出されるもので、呼び出しをこちらで意識する必要はありません。呼び出された時に何を描画するかだけを実装すれば良いのです。

まず、背景の描画を行います。ライフゲームは時間の経過と共に、セルの状態を遷移させていくものなので、古い世代のセルを新しい世代のセルで塗り替える必要があります。

古い状態を一度全て消すために、updateメソッドの先頭でbackgroundメソッドを呼び出して、全体を背景色で塗りつぶしています。

背景描画によるお掃除が終わったら、現在の状態のセルを描画します。fill(self.cell_color)でセルの色を指定したあと、行と列の数の分、ループ処理を行い、各セルの状態(0 or 1)に基づいて、セルを描画します。

セルが0の場合は「死」を表しており、そこにセルは存在しなくて良いため、セルの状態が「1」の場合だけ、セルの描画処理を行います。

def update(self):
        
    # 背景色を描画
    background(self.background_color)
        
    # セルの色せをセット
    fill(self.cell_color)
        
    # 行数分のループ
    for row in range(self.row_num):
            
        # 列数分のループ
        for col in range(self.col_num):

            # セルの状態をチェックして、状態がON(1)の場合はセルを描画する。
            # 状態がOFF(0)は、何もしないため、背景が表示されたままの状態となる。
            if self.cells[row][col]:

                # セル(四角系で表現する)を描画する。
                # 縦横の長さをcell_sizeにするとセル同士が繋がって見えてしまうので、-1して境界が見えるようにする。
                rect(col * self.cell_size, row * self.cell_size, self.cell_size - 1, self.cell_size - 1)

ここまで書けたら、一度プログラムを実行してみましょう。間違っていなければ、以下のようにセルが表示されるはずです。

f:id:mitsu3204:20181018013152j:plain

現在の状態では、セルの状態遷移を実装していないため、初期表示のみ行ってそこから何も変化は起きません。

次は、このセルの状態は一定時間ごとに変化するように実装を加えていきます。

セルの次の世代を計算する

各セルの生死は、現在の周りのセルの生死の状態によって決まります。周りのセルと言っているのは、自セルの上下左右斜めの合計8つのセルです。

この8つのセルの中に「生」の状態のセルがいくつ存在するかによって、自セルが次の世代で生きるか死ぬかが決まるというのがライフゲームのルールです。

ライフゲームのルール

  • 誕生:「死」の周辺セルの生存数が3の場合、次の世代が誕生する。(0 -> 1)
  • 生存:「生」の周辺セルの生存数が2または3の場合、次の世代でも生存する。(1 -> 1)
  • 過疎:「生」の周辺セルの生存数が1の場合、次の世代は死滅する。(1 -> 0)
  • 過密:「生」の周辺セルの生存数が4以上の場合、次の世代は死滅する。(1 -> 0)

指定したセルの周辺セルの生存セル数を数えるメソッドを実装します。

def count_alive_cells(self, r: int, c: int):
    """指定したセルの周辺の生存セルの数を返します。
  """
    alive = 0
    if r > 0:
        if c > 0:
            if self.cells[r - 1][c - 1]:
                alive += 1
        if self.cells[r - 1][c]:
            alive += 1
        if c < self.col_num - 1:
            if self.cells[r - 1][c + 1]:
                alive += 1

    if c > 0:
        if self.cells[r][c - 1]:
            alive += 1
    if self.cells[r][c]:
        alive += 1
    if c < self.col_num - 1:
        if self.cells[r][c + 1]:
            alive += 1

    if r < self.row_num - 1:
        if c > 0:
            if self.cells[r + 1][c - 1]:
                alive += 1
        if self.cells[r + 1][c]:
            alive += 1
        if c < self.col_num - 1:
            if self.cells[r + 1][c + 1]:
                alive += 1
    return alive

上記のcount_alive_cellsメソッドで、現在の生の状態のセル数を計算して、ルールに基づいて、次の世代のセルを作成するのが以下のメソッドです。

def gennext_cells(self):
    """現在のセルの状態に基づいて次の世代のセルを返します。
    """
    rows = []
    for r in range(self.row_num):
        cols = []
        for c in range(self.col_num):
            alive = self.count_alive_cells(r, c)
            if alive == 2:

                # 現在の状態を引き継ぐ
                cols.append(self.cells[r][c])

            elif alive == 3:

                # 誕生する
                cols.append(1)
            else:
                cols.append(0)
            rows.append(cols)
    return rows

updateメソッドの末尾に、世代交代のメソッドの呼び出しを追加します。

また、そのまま実行すると目まぐるしくセルの状態が変化して目が追いつかないため、最後にスリープ処理を追加して、少しだけ処理を止めるようにします。timeモジュールを使うので、ファイルの冒頭にimport timeの記述も追加しましょう。

def update(self):

    〜 省略 〜

    # 次の世代のセルを取得
    self.cells = self.gen_next_cells()

    # 世代交代の速度調整のため少しスリープさせる
    time.sleep(0.05)

これで時間とともに状態が変化するライフゲームの完成です。

実行ボタンをタップして起動してみましょう。

しばらく動かしていると、セルの形が固定パターンに落ち着くか、特定のパターンを延々と繰り返す状態になると思います。(これは正常な動きです)

タップした箇所にセルを配置するように機能を追加する

せっかくなので、タップ操作に反応する機能も実装してみます。

画面をタップしたら、タップした箇所に新しいセルを追加するよう機能を追加みます。

まずは、指定した座標(x, y)に該当するセルの状態をONにするメソッドをMySceneクラスの中に作ります。

xとyは、タップした位置の座標の情報を受け取る想定です。

座標を一つのセルのサイズで割って、該当のセルの行と列のインデックスを計算しています。

位置を取得したら、その部分のセルの状態をON(生存状態)にして、描画処理を行います。

def add_cell(self, x, y):
    """指定座標にセルを追加します。
    """

    # 位置の計算
    row = int(y / self.cell_size)
    col = int(x / self.cell_size)

    # 該当のセルの状態をONに変更
    self.cells[row][col] = 1

    # セルを描画
    rect(col * self.cell_size, row * self.cell_size, self.cell_size - 1, self.cell_size - 1)

上記のメソッドは、画面をタップした時に呼び出します。画面をタップすると、touch_beganメソッドが呼び出されます。

元々このメソッドの中身の実装は空っぽでしたが、座標情報を指定してadd_cellを呼び出すように変更します。タップした箇所の座標情報は、touch_beganメソッドに渡されるtouchlocationプロパティから取得することができます。

def touch_began(self, touch):
    x, y = touch.location
    self.add_cell(x, y)

また、タップしたあとに、指をそのまま画面上で動かした際にもセルを配置するように、タップと同等の処理を行うようにします。今度はtouch_movedメソッドにtouch_beganメソッドと全く同じ内容を実装します。

def touch_moved(self, touch):
    x, y = touch.location
    self.add_cell(x, y)

これで完了です。

プログラムを実行して画面をタップすると、タップした位置に新しいセルが配置されるようになっています。

まとめ

簡単な実装のみ行いましたが、もっと凝った作りにしてみたい人や、UIコンポーネントの使い方も練習したい人は、世代交代の速度を調整する機能や、ボタンによる一時停止、再開機能、また、セルの状態のリフレッシュ機能なども実装してみると良いかもしれません。

以上です。

Pythonista 3は、App Storeからダウンロードできます。

Pythonista 3 / omz:software

f:id:mitsu3204:20181016133630j:plain

2018-10-15 botトレード成績

今日のビットコインは、日中大きく動きましたね。

気づいて少し調べたところUSDT起因でした。(USDTは急激な下げ)

本日のトレード

現在、bitFlyerで取引している私のボットは、トレンドの初期に現れるシグナルに従って、順張りでエントリーします。

今日はというと、14時頃からエントリーしていました。

これは、bitFlyer のFXBTCJPYのチャートです。矢印の箇所が、ボットのエントリータイミングです。

f:id:mitsu3204:20181016020914p:plain

良いタイミングでエントリーしています。価格が上がりきって、少し下げだした16時頃にポジションをクローズしていました。

今日大きく勝ったのはこの時くらいで、あとはトレードはしていますが、小さな負けと勝ちを繰り返していました。

急な変動に対応できるのはボットの強み

ボットを稼働していると、このような急な動きにも自動で対応できるのが強みです。

あとで気づいて「あっ利益出てる」なんてことがよくあります。(大きく動いていたのに、取引所がビジー状態で注文が通っていなかったなんてこともありましたが・・)

今月だと、15日だけでなく11日の朝にも、約4万円幅の急激な下落がありましたが、その際もボットがトレードしているので、ショートできっちり下落した分が利益となりました。

今日のように大きな利益が取れることはまれ

上記のエントリータイミングを見ると、とてもうまくいっているように見えますが、普段から上記のような変動の初期には常にエントリーをしています。

最近は価格が大きく動かない日のほうが多いので、エントリーしては損切りを繰り返しています。私が運用しているボットの場合、勝率は3割程度しかないため、損切りしている時のほうが多いのです。

この勝率3割というのは、特別低いわけではないと思います。トレンドフォロータイプのボットは、大体この程度じゃないでしょうか。

それでも、この日のように大きく動いた日に一気に大きな利益を確保することができるため、月単位で見ると損益はプラスとなります。

肝心なのは、負けトレードが続いても、狼狽してボットを止めないことです。

Quoine ExchangeのPrivate APIの認証をGoから実行する

f:id:mitsu3204:20181014135327j:plain 今作っているツールをGoで書いていて、Quoine ExchangeのPrivate APIを呼び出す必要があったので、API認証について調べていました。

仮想通貨の自動トレードにはPythonを使っている人が多いと思いますが、ccxtやAPIクライントのライブラリを使用している場合は、APIの認証方法なんて意識する必要もないと思います。

www.hacky.xyz

Quoine ExchangeのAPI認証

Quoine Exchange のAPIドキュメントに認証方法についての説明とサンプルコードが掲載されています。

f:id:mitsu3204:20181014124542p:plain

Quoine ExchangeのAPI認証には、JWT (JSON Web Token)という認証方法が使用されています。

サンプルコードが提示されているのはRubyのコードのみですが、他の言語で認証コードを実装する場合も同じ事をやれば良いだけです。

認証するにあたり、自分のアカウントのAPIトークンID(数字)とAPIシークレット(長ったらしい文字列)を用意する必要があります。 これらは取引所のサイトから発行可能です。

読んでみる

サンプルコードは、product_id=1というパラメータ(たぶんBTCUSD)を指定して、自分の注文情報の一覧を取得するordersというプライベートAPIを実行しています。

認証に必要な情報の準備

サンプルコードを見ると、認証に必要な情報は以下のとおりであることがわかります。

これらの情報をキー、バリュー形式で格納したauth_payloadを作成しています。

token_id = 'YOUR_API_TOKEN_ID'
user_secret = 'YOUR_API_SECRET'
path = '/orders?product_id=1'

auth_payload = {
  path: path,
  nonce: DateTime.now.strftime('%Q'),
  token_id: token_id
}

nonceは、DateTime.now.strftime('%Q')の部分で、現在時刻のタイムスタンプ文字列を生成しています。

呼び出すAPIが注文情報一覧取得API(orders)でない場合は、pathの部分は変更する必要があります。

署名を作成

必要な情報を格納したauth_payloadというオブジェクトを作成したら、その内容をJWTのライブラリを使ってエンコードしています。

その際に、アカウントのAPIシークレット(user_secret)を使用しています。

signature = JWT.encode(auth_payload, user_secret, 'HS256')

HTTPヘッダに署名情報を追加

JWT.encodeによって作成した署名情報は、X-Quoine-Authと言う名前でHTTPヘッダに追加しています。

request.add_field('X-Quoine-Auth', signature)

Goで実装する

GoにもJWTのライブラリはあります。

github.com

まずは、jwt-goを入手します。

go get github.com/dgrijalva/jwt-go

import

import文にjwt-goを追加します。

import (
    ...
    
    jwt "github.com/dgrijalva/jwt-go"
)

認証に必要な情報の準備

サンプルコードと同じ様に、認証のためのペイロードを作成します。jwtのMapClaimsとして作成します。

nonceは、現在時刻のタイムスタンプです。(API実行ごとに値が変わりさえすれば何でも良いですが)

token := jwt.New(jwt.GetSigningMethod("HS256"))
token.Claims = jwt.MapClaims{
    "path":  path,
    "nonce": strconv.FormatInt(time.Now().Unix(), 10),
    "token_id": "APIキー",
}

署名を作成

作成したtokenを介して署名作成用の関数を呼び出します。その際にAPIシークレットを使用します。

signature, err := token.SignedString([]byte("APIシークレット"))

HTTPヘッダに署名情報を追加

作成した署名はサンプルのとおり、X-Quoine-Authの名前でHTTPヘッダにセットするだけです。

req, _ := http.NewRequest(strings.ToUpper(method), "https://api.liquid.com"+path, nil)
req.Header.Set("X-Quoine-Auth", signature)
req.Header.Set("X-Quoine-API-Version", "2")
req.Header.Set("Content-Type", "application/json")

あとはこのリクエストを送信すればOKです。

client := new(http.Client)
res, err := client.Do(req)

以上

【英語学習】Kindleなら洋書が簡単に読めるようになる!Kindleの素晴らしい機能

f:id:mitsu3204:20181011002215j:plain

エンジニアたるもの技術ばかりだけでなく、多少は英語にも触れておかなくてはと思っており、技術書ばかりではなく簡単な洋書も多少は読むように心がけております。

洋書を読む際には、Kindleを使って読むと捗るので、その点についてご紹介したいと思います。

目次

  • 意味がわからない単語は1タップで辞書が解決
  • 意味がわからない文章も選択してその場で翻訳
  • 難しい単語の簡単な表現を示してくれるWord Wise機能
  • まとめ

意味がわからない単語は1タップで辞書が解決

Kindleでは無料で辞書を使うことができるので、わからない単語が出てきたらその場ですぐに解決できてしまうのです

ググったり、翻訳アプリを起動したりせずに、Kindle上でそのまま単語を調べられるのでとても効率が良く、単語を調べながらの読書が非常にスムーズに行えるのです。

操作方法は簡単です。文章を読んでいてわからない単語が出てきたら、画面をタップして単語を選択します。すると、 自動で辞書を検索して結果を表示してくれます~。

f:id:mitsu3204:20181010235143p:plain

意味がわからない文章も選択してその場で翻訳

単語ではなく文章がわからない場合でも、単語の場合と同様で画面をタップして文章を選択するとメニューが表示されるので、翻訳を選択すれば、Bing Translator による翻訳結果が表示されます。

勉強として洋書を読んでいると、わからない単語や文は必ず出てきます。単語の時と同様、PCなどを操作することもなく、Kindle上ですぐに翻訳して解決できてしまうのはのです

f:id:mitsu3204:20181010235507p:plain

難しい単語の簡単な表現を示してくれるWord Wise機能

KindleのWord Wise機能は、単語に対して、同じ意味で異なる表現を示してくれる機能です。Word Wise機能による異なる表現は、元の文章のすぐ上に自動的に小さく表示してくれます。

同じ意味を示す単語でも、異なる表現を知ることによって、ニュアンスをより正確に知ることができ、理解が深まる場合があります

f:id:mitsu3204:20181011000448j:plain

このWord Wise機能は、全ての電子書籍で使用可能なわけではなく、電子書籍側が対応している必要があります。

また、微妙な表現が表示される場合もあるので、人によってはWord Wise機能による表示が鬱陶しい場合もあるかもしれません。その場合は、設定にてWord Wise機能をオフにすることができます。

AmazonならLexile指数で自分の英語レベルに合った洋書を見つけられる

Lexile(レクサイル)指数 というのは、英語の読解力を評価する指標のことです。

Amazonのストアでは、このLexile(レクサイル)指数の範囲から洋書を探すことができるので、現在の自分のLexile指数がどの程度なのかを把握して、自分のレベルにあった洋書を見つけることができるのです 。

Lexile(レクサイル)指数について、Amazonのページには以下のように掲載されています。

Lexile指数は、英語の読解力を客観的に測定するツールとして開発された指標で、英文に使われている単語数や難易度、構文の複雑さなどを総合的に数値化したもの。本の場合はその難易度を、人であれば「読む力」を示す。

指数は「0L」から10刻みに上がり、難解な専門書は「2000L」を超える。

アメリカでは教育現場で幅広く活用されているほか、世界165か国で使用されている。

Lexile指数の範囲によるレベルの目安は以下のとおりです。

Lexile指数とアメリカの学年の対応の目安

  • 1年生 (-300L)
  • 2年生 (140L-500L)
  • 3年生 (330L-700L)
  • 4年生 (445L-810L)
  • 5年生 (565L-910L)
  • 6年生 (665L-1000L)
  • 7年生 (735L-1065L)
  • 8年生 (805L-1100L)
  • 9年生 (855L-1165L)
  • 10年生 (905L-1195L)
  • 11・12年生 (940L-1210L)

日本に置き換えると、中学生で700L強〜1100L弱、高校生で900L〜1200Lといったところでしょうか。

Lexile指数で洋書を探せるのは、Amazonのストアとしての機能なので、Kindleは関係ありません。紙の書籍も検索できます。

f:id:mitsu3204:20181011002722p:plain

まとめ

単語や文章の意味がわからない場合に、PCやスマホで調べずに、Kindle上でそのまま1タップの操作で解決できることって、素晴らしいことだと思います。

手間も少ないし調べるために集中力を削がれることもありません。また、利用可能な書籍は限られるものの、Word Wise機能も単語の理解を深めるために役に立ってくれるし、面白い機能だと思います。

勉強できる時間も限られているので、こういう便利なものはどんどん取り入れて、学習効率を高めて行きたいです。

私は、現在は「Kindle Oasis 2017(8GB、Wifiモデル、キャンペーンなし)」を使用しています。スマートフォンの画面と違って、長時間の読書や暗い部屋での読書でも目が疲れにくいので、Kindleアプリよりも圧倒的にKindle端末がオススメです。

MacBook Pro バッテリートラブル|充電が残っているのに電源が落ちる!?

f:id:mitsu3204:20181007143853j:plain

メイン機として使用しているMacBook Pro にバッテリーの不調が起きてしまいました。同じ症状で困っている人がいるかもしれないので、私が行なった対応について、記録を残しておきます。

目次

対象のMac

症状

バッテリーの残量が大体50%〜70%程度のところで電源が突然落ちるようになってしまいました。

電源が落ちた後は、電源ボタンを押してもバッテリー切れのサインがディスプレイに表示され、起動できません。

電源アダプターを接続すれば、起動できるのですが、起動直後にバッテリーの残量表示を見ると、やはり50%〜70%残っていると表示されます。

フル充電の状態から突然落ちるまでの時間は、その時によって多少前後はするものの、大体2時間程度なので、バッテリーを使い切ったとは考えにくく、バッテリー残量の表示が狂っているという気はしません。

Macの状態

対象のMacBook Proは2017年モデルで、同年の夏に購入したものです。症状がで出したのは、2018年9月からなので、それまでの利用期間は一年とちょっとという程度です。

Macのシステムレポートで、バッテリーの状態に関する情報を確認したところ、ステータスは「正常」と表示されています。また、充放電回数は130回程度です。

f:id:mitsu3204:20181007142445p:plain

上記の情報は「このMacについて」-> 「システムレポート」と選択してレポート画面を開き、左側のリストから「電源」を選択すれば表示できます。画像は英語版ですが、日本語表示だと「状態情報」の下に「充放電回数」と「状態」という名称で表示されています。

製造工程でのバッテリーの不具合ではないか?

バッテリーのトラブルに関してググっていた時に以下のページを発見しました。

f:id:mitsu3204:20181007180215p:plain

13 インチ MacBook Pro (Touch Bar 非搭載) バッテリー交換プログラム - Apple サポート

2016年10月から2017年10月の間に製造されたTouch Bar非搭載の13インチ型MacBookの一部で、バッテリーが膨張する問題があるようで、対象のMacBook Proは、バッテリーを無償で交換するとのことです。

対象であるかどうかは、上記のページの入力フォームにMacBook ProのシリアルNo.を入力すればすぐに判明します。

型や製造年月的には、私のMacBook Proも該当しているので、もしやと思いシリアルNo.を入力してみたのですが、対象外と表示されました。

f:id:mitsu3204:20181007180126p:plain

※条件に該当するMacBook Proをお使いのかたは、トラブルが起きていなくても一応確認しておいたほうが良いかと思います。

対応

1.SCMリセット

電源管理の機構の異常の可能性が高いと思い、まずはSMC (システム管理コントローラ)のリセットを試してみました。

SMCリセットの方法は簡単で、Macの電源を落として、Shift、Control、Optionと電源ボタンを同時に一定時間以上押し続けるだけです。

Macのモデルによって若干手順が異なるので、詳しい手順については以下の公式ページをご覧ください。

Mac の SMC (システム管理コントローラ) をリセットする方法 - Apple サポート

結果

SMCリセットを行なったても、症状は全く改善されませんでした。

2.NVRAMリセット

バッテリーの問題とは関係ないかもしれませんが、原因がはっきりとわからないため、一応「NVRAM(不揮発性ランダムアクセスメモリー)」のリセットも行いました。

こちらも手順はSMCリセットと似ていて、起動時に複数のキーを一定時間押し続けるだけです。

NVRAMの場合は、電源を落とした状態で、Command、Option、P、Rを同時押し20秒間押しっぱなしにすれば、リセットが完了します。

Mac で NVRAM または PRAM をリセットする - Apple サポート

結果

こちらも症状の改善は見られませんでした。

3.OSクリーンインストール

ちょうどMojaveがリリースされた時期であり、Mojaveへのアップデートついでに、OSをクリーンインストールしました。

不要なゴミを削除して、快適な状態を保つために、私は一年に1、2回程度は、OSをクリーンインストールしています。

f:id:mitsu3204:20181010210050p:plain

無事にクリーンインストールが終わり、早速ダークモードで使っています。

結果

これもダメでした!まったく症状は改善されず・・・

4.バッテリーを自分で交換

まだ原因は判明していませんが、こうなると恐らくバッテリーが悪いのだろうと思いました。

バッテリーの交換なら、バッテリーだけ購入して、交換作業は自分でやるということもできると思うのですが、調べてみたところ、最近のモデルだとバッテリーの交換は結構面倒臭そうです。

gigazine.net

それと、私が使用しているMacBook Proの型は「A1708」なのですが、これに対応するバッテリー自体がなかなか検索しても見つかりませんでした。

一応、以下のバッテリーを見つけたのですが、価格がとても高いです。

JIAZIJIA Apple A1713 (11.4V 4781mAh/54.5Wh) MacBook Pro 13インチ A1708 2016 2017 EMC 2978 MLL42CH/A MLUQ2CH/A シリーズ ノートブック A1708 020-00946 A1708(EMC 2978)

これしか見つからなかったので、価格の比較ができてないのですが、普通はバッテリーって数千円程度だと思っています。

バッテリー交換を自分で行うメリットは、お金がかからないことだと思うのですが、アップルのジーニアスバーでのバッテリー交換料金は、12,800円なので、この値段だと自分でやる意味は無さそうです。

ということで、この対応案は採用せず。(そもそも本当にバッテリーが悪いかわからないし)

5.アップルストアジーニアスバーで修理依頼

アップルストアに持ち込んで見てもらうことにしました。

ジーニアスバーへの持ち込みでの修理依頼は、アップルのサイトからオンラインで予約できます。私はアップルストア新宿で予約しました。

f:id:mitsu3204:20181010205941p:plain

で、早速ジーニアスバーへ問題のMacBook Proを持っていき、ジーニアスバーの人に見てもらったのですが、電源ケーブルを挿すUSBポート部分の部分が緩い気がするとのこと。

お店でMac電源ケーブルを挿した際には充電が始まらず、何度か抜き差ししてたらやっと反応しました。私の使用しているMacBook Proは2ポートのモデルですが、両ポートとも同様でした。

問題の症状の発生以降、自宅で使用していた際にも一度だけ充電が始まらないことがありましたが、それ以降同様の事象が起きなかったので、たまたまかと思っていましたが、原因と関係あるんでしょうか・・・

ジーニアスバーの人が言うには、接触が悪いとバッテリー残量は上がっても、実際にはバッテリーへの充電が十分に行われないケースがあるとのことでした。

もし、USBポートの接触不良が原因であれば、ロジックボードごと交換という対応になるようです。その際の料金は45,000円とのことです。

結局、詳細まで調べて原因を特定するには、MacBook Proをアップルへ数日間預ける必要があるということで、私としては現在は他にマシンが無く、預けると何もできなくなってしまうため、預けずに帰ってきました。

現在

というわけで、直っていません。

数日間もマシンが使えないのは仕事に支障が出るし、現実的ではありません。

一時的に代替機用意するか、このままの状態で常に電源ケーブルと共に使い続けるか、対応を検討中です。それに、直すにしても45,000円というのは、なかなかお高いですね。

【個人的まとめ】技術書の電子書籍販売サイト

f:id:mitsu3204:20181001135657j:plain 技術書を購入する際は、紙の書籍で買っているでしょうか?私は現在では、電子版が販売されていれば、電子版を優先して購入するようにしています。

今回は、私の電子書籍の購入に利用している3つのサイトについて、どんなものか記事にしてみました。

  1. オライリー Eブックストア
  2. Gihyo Digital Publishing
  3. Kindleストア(Amazon

オライリー Eブックストア

f:id:mitsu3204:20181001132056p:plain

O’Reilly Japan Ebook Store

オライリージャパンでは、電子書籍の販売サイトを運営しています。

Amazonでは、オライリーの技術書は紙の書籍しか販売されていませんが、オライリーのEブックストアでは、電子版を購入できます。

全ての本がDRMフリーである

オライリーEブックストアで販売されている電子書籍DRMフリーです。

よって、購入した電子書籍は、端末もOSもアプリにも縛りはなく、好きな端末に入れて読むことができます。

PDF、EPUB、MOBI形式が全て用意されている

このオライリーのEブックストアの良いところは、複数のファイル形式を利用できるところです

書籍にもよりますが、最近はPDF、EPUB、MOBIの3つの形式が用意されているものが多いです。私の知る限りでは、数年前まではPDFしかダウンロードできなかったのですが、最近はEPUBや、MOBIがよく対応されています。

購入済み書籍の一覧画面に、ファイルフォーマットごとのボタンが表示されており、ボタンをクリックすると該当のフォーマットのファイルをダウンロードできます。

どれか一つを購入するのではなく、用意されている全てのフォーマットをいつでもどれでもダウンロードできます。

f:id:mitsu3204:20181001131348p:plain

私は、オライリー本を購入する場合は全てこのオライリーEブックストアで購入して、MOBIファイルをKindleに入れて、Kindle Oasisで読んでいます。

電子書籍の発売日は紙より遅い

全てかどうかは把握できてないのですが、今までの傾向を見ていると、電子書籍の発売日は紙の書籍の発売日より遅くなることが多いようです。

Gihyo Digital Publishing

f:id:mitsu3204:20181001133124p:plain

技術評論社電子書籍の販売サイトです。

PDF、EPUBを利用可能

PDF形式のみの書籍が多いようですが、EPUBが用意されている書籍もあります。MOBIファイルは扱ってないようです。

PDFやEPUBの場合は、MaciOSの標準アプリである「ブック」が一番読みやすいと思います。PDFだとEPUBやMOBIと違って、文字サイズのみを変更する機能は備わってないですが、iPad(ミニでない)なら問題なく読めると思います。

Kindleストア(Amazon

f:id:mitsu3204:20181001134705p:plain

Kindle本 電子書籍 | Amazon | アマゾン

恐らく品揃えは最も豊富なんじゃないでしょうか。様々な書籍がKindle版として購入可能です。 セールも頻繁にやっているので、電子書籍を安く購入できるチャンスも多いです。

フォーマットはMOBIのみ

購入できる電子書籍のフォーマットがmobiファイルとなるため、基本的にKindle端末やスマートフォンやPCのKindleアプリで読むことになります。

PCやスマートフォンなど、各デバイス向けにKindleアプリが提供されているので、MOBIに限定されてもあまり困ることはないと思います。

豊富な品揃え

当然のことながら各社の出版物が販売されているので、購入可能な電子書籍は豊富です。本屋にいるのとほぼ変わりません。

おわりに

個人的には、技術書であればDRMフリーでフォーマットも複数用意しているオライリーのEブックストアが最高!って思ってます。

技術書に限定して記載しましたが、技術書以外を購入する場合は、ほとんどKindleストアで購入しています。一部は紀伊国屋でも購入しています。