DEVGRU

プログラミングと競馬予想について書きます

Python と pypetteer で某所から株価を無料で取得する

結局、仮想通貨は逃げるタイミングが遅れてとんでもない負債を私に残していったので、 ボラリティは低いが安定している株取引を粛々とすることにした。

さて、株取引の自動化は厳しいが、せめて売買のタイミングぐらいは自動的に分かるようにしておきたい。

幸い、無料で株価履歴を公開しているサイトがあるので、そこから自動取得するようにしてテクニカル指標を求めるようにすることにした。

import os
import asyncio
import time

from pyppeteer import launch

import pandas as pd
import matplotlib.pyplot as plt

async def scrape(browser, url):
    page = await browser.newPage()
    await page.goto(url)
    await page.waitFor('tr')
    elements = await page.JJ('tr')
    
    result = []
    for element in elements[1:]:
        values = (await element.getProperty('textContent')).toString().split()[1:]
        date, o, h, l, c, volume, _ = values
        result.append([date, int(o), int(h), int(l), int(c), int(volume)])
    return result

async def main():
    browser = await launch()
    stock_id = 3341
    result2017 = await scrape(browser, f'https://kabuoji3.com/stock/{stock_id}/2017/')
    result2018 = await scrape(browser, f'https://kabuoji3.com/stock/{stock_id}/2018/')
    result = result2017 + result2018
    await browser.close()
    
    print(result)
    
asyncio.get_event_loop().run_until_complete(main())

stock_id を適当な銘柄番号にすると2017/1/1〜の日付、OHLC, Volumeが取得できます。

note で Botのコードを記事にして売ってみた

BTC・FXのトレード関係の情報をnoteで売るのが流行っている(というかドテンくん)ので、 ちょっとやってみました。

note.mu

前2記事の画面表示機能+Bot機能で900円です。

Botは1コインあたり5000円買って12%で利喰い、-8%で損切りするのを繰り返すだけです。 もちろんいくら買うか、利喰い損切りのしきい値も変更可能です。

買い時の判定コードはTradingView でVixFix使ったものを移植しましたが、お好きなものに入れ替えられます。

利益は保証できませんが、0.5BTC突っ込んで3日で2千円ぐらいなので悪くないかなと。

ぜひ買ってお試しください。

Binance の手持ちの草コインの価格上昇・下落・これまでのトレード成績が分かるようにした

こんな記事を書いた。 コードを改良したので続き。

team-6.hatenablog.jp team-6.hatenablog.jp

前回のコードをちょいちょい見直したら結構違うコードになった。

追加になったのは、これまでのトレードの利得を最後に表示するようになった点だ。

f:id:katoken-0215:20180515084723p:plain

API呼び出しに時間がかかるので注意。

ALL_COINS はそのうち使うので残しておく。

同じディレクトリにkeys.json をおいて、中にAPI KeyとAPI Secretを記述すること(フォーマットはコードから類推してくださいです)。

pip install requests python-binace
#!/usr/bin/env python

import json

import requests
from binance.client import Client
from binance.exceptions import BinanceAPIException

ALL_COINS = ['BTC', 'LTC', 'ETH', 'BNC', 'ICO', 'NEO', 'BNB', '123', '456', 'QTUM',
             'EOS', 'SNT', 'BNT', 'GAS', 'BCC', 'BTM', 'USDT', 'HCC', 'HSR', 'OAX',
             'DNT', 'MCO', 'ICN', 'ELC', 'PAY', 'ZRX', 'OMG', 'WTC', 'LRX', 'YOYO',
             'LRC', 'LLT', 'TRX', 'FID', 'SNGLS', 'STRAT', 'BQX', 'FUN', 'KNC', 'CDT',
             'XVG', 'IOTA', 'SNM', 'LINK', 'CVC', 'TNT', 'REP', 'CTR', 'MDA', 'MTL',
             'SALT', 'NULS', 'SUB', 'STX', 'MTH', 'CAT', 'ADX', 'PIX', 'ETC', 'ENG',
             'ZEC', 'AST', '1ST', 'GNT', 'DGD', 'BAT', 'DASH', 'POWR', 'BTG', 'REQ',
             'XMR', 'EVX', 'VIB', 'ENJ', 'VEN', 'CAG', 'EDG', 'ARK', 'XRP', 'MOD',
             'AVT', 'STORJ', 'KMD', 'RCN', 'EDO', 'QASH', 'SAN', 'DATA', 'DLT', 'GUP',
             'MCAP', 'MANA', 'PPT', 'OTN', 'CFD', 'RDN', 'GXS', 'AMB', 'ARN', 'BCPT',
             'CND', 'GVT', 'POE', 'ALIS', 'BTS', 'FUEL', 'XZC', 'QSP', 'LSK', 'BCD',
             'TNB', 'GRX', 'STAR', 'ADA', 'LEND', 'IFT', 'KICK', 'UKG', 'VOISE', 'XLM',
             'CMT', 'WAVES', 'WABI', 'SBTC', 'BCX', 'GTO', 'ETF', 'ICX', 'OST', 'ELF',
             'AION', 'WINGS', 'BRD', 'NEBL', 'NAV', 'VIBE', 'LUN', 'TRIG', 'APPC', 'CHAT',
             'RLC', 'INS', 'PIVX', 'IOST', 'STEEM', 'NANO', 'AE', 'VIA', 'BLZ', 'SYS',
             'RPX', 'NCASH', 'POA', 'ONT', 'ZIL', 'STORM', 'XEM', 'WAN', 'WPR', 'QLC',
             'GRS', 'CLOAK', 'LOOM', 'BCN']

IGNORE_COINS = ['BTC', 'BNC', 'ICO', '123', '456', 'BTM', 'USDT', 'PAY', 'LRX', 'FID',
                'CVC', 'STX', 'CAT', 'PIX', '1ST', 'CAG', 'EDG', 'AVT', 'QASH', 'SAN',
                'DATA', 'GUP', 'MCAP', 'OTN', 'CFD', 'ALIS', 'GRX', 'STAR', 'IFT', 'KICK',
                'UKG', 'VOISE', 'SBTC', 'BCX', 'ETF']

class Coin:
    class Status:
        def __init__(self, symbol, btc_amount, amount, position, price, ratio, profit):
            self.symbol = symbol
            self.btc_amount = btc_amount
            self.amount = amount
            self.position = position
            self.price = price
            self.ratio = ratio
            self.profit = profit

    def __init__(self, symbol, amount, client):
        self._symbol = symbol
        self._amount = amount
        self._client = client

        self._btc_amount = 0
        self._position = 0
        self._profit = 0
        self._ratio = 0

    def _get_price(self):
        recent_trade = self._client.get_recent_trades(symbol=f'{self._symbol}BTC', limit=1)
        return float(recent_trade[0]['price'])

    def _get_current_position_and_profit(self):
        position = 0
        amount = 0
        profit = 0
        try:
            trades = self._client.get_my_trades(symbol=f'{self._symbol}BTC')
            for trade in trades:
                qty = float(trade['qty'])
                price = float(trade['price'])
                if trade['isBuyer']:
                    position = (amount * position + price * qty) / (amount + qty)
                    amount += qty
                else:
                    profit += price - position
                    amount -= qty
            return position, profit
        except BinanceAPIException:
            return 0, 0
        except Exception as e:
            print(e)
            return 0, 0

    def get_current_status(self):
        position, profit = self._get_current_position_and_profit()
        if self._amount > 0 or profit != 0:
            if self._amount > 0:
                price = self._get_price()
                btc_amount = price * self._amount
                ratio = ((price - position) / position) * 100
            else:
                price = 0
                btc_amount = 0
                ratio = 0

            return Coin.Status(self._symbol, btc_amount, self._amount, position, price, ratio, profit)
        else:
            return None


class Trader:
    def __init__(self, key, secret):
        self._client = Client(key, secret)

    def coin_factory(self, symbol, amount):
        return Coin(symbol, amount, self._client)

    def print_status(self):
        account = self._client.get_account()

        btc_total = 0
        btc_profit_total = 0

        for balance in account['balances']:
            amount = float(balance['free']) + float(balance['locked'])
            if balance['asset'] == 'BTC':
                print(f'BTC:\t{amount}')
                btc_total += amount
            elif balance['asset'] not in IGNORE_COINS:
                coin = self.coin_factory(balance['asset'], amount)
                status = coin.get_current_status()
                if status is not None:
                    print(f'{status.symbol}:\t{status.btc_amount:.3f}({status.amount:8.2f})\t{status.position:.10f}\t({status.price:12.10f} {status.ratio:5.2f}%)\t{status.profit:13.10f}')

                    btc_total += status.btc_amount
                    btc_profit_total += status.profit

        print('Total:', btc_total)
        response = requests.get('https://api.cryptowat.ch/markets/bitflyer/btcjpy/price')
        btcjpy_price = response.json()['result']['price']
        print('Total(JPY):', btc_total * btcjpy_price)
        print('Total profit:', btc_profit_total)
        print('Total profit(JPY):', btc_profit_total * btcjpy_price)

if __name__ == '__main__':
    with open('keys.json', 'r') as f:
        keys = json.load(f)
        trader = Trader(keys['binance']['key'], keys['binance']['secret'])
        trader.print_status()

先の2つの記事含めコードのライセンスはUnlicense, もちろん無保証、無責任で。

月刊仮想通貨Vol,3 (プレジャームック)

月刊仮想通貨Vol,3 (プレジャームック)

アフター・ビットコイン: 仮想通貨とブロックチェーンの次なる覇者

アフター・ビットコイン: 仮想通貨とブロックチェーンの次なる覇者

仮想通貨リップルの衝撃 Rippleが実現する

仮想通貨リップルの衝撃 Rippleが実現する"価値のインターネット"

世界は逆転する! 仮想通貨サービス・ICOで世界を変える

世界は逆転する! 仮想通貨サービス・ICOで世界を変える