ぼくのかんがえたさいきょうの株式投資あるごりずむ

# はじめに
こんにちは、イナズマという者です。普段は競技プログラミングで遊んでいます。
Qiita記事を書くのは初めてですので、お手柔らかにお願いします。
(初めてなのに強気なタイトルでごめんなさい)(残念ながらもちろん全然最強ではありません…)

# 今回の記事について
今回は[QuantX](https://factory.quantx.io/)というツールで株式投資のアルゴリズムを書いて得た知見を共有したいと思います。株式投資についても素人なのでお手柔らかにお願いします。

# やったこと
## サンプルコードを読み込む
とりあえずサンプルコードを読んでみました。サンプルコードは、QuantXにログインし、「開発デモを体験する」をクリックすると読めるかと思います。
[ドキュメント](https://factory.quantx.io/handbook/ja/)に、サンプルコードを用いたチュートリアルがあるので、QuantXでどのようにアルゴリズムを書くかの雰囲気を感じることができます。

## アルゴリズムを考える
サンプルコードを読んでみると、どうやら移動平均線([移動平均線のwiki](https://ja.wikipedia.org/wiki/%E7%A7%BB%E5%8B%95%E5%B9%B3%E5%9D%87%E7%B7%9A))というものを用いているようです。この移動平均線を用いたアルゴリズムも改良のしようはあるようですが、投資素人の私には改良の目処は立ちませんでしたし、他のテクニカル分析指標([ここ](https://www.sevendata.co.jp/shihyou/index.html)に乗っているようなもの)を用いたアルゴリズムを書くにも、テクニカル指標について勉強が必要そうでした

# ぼくのかんがえたさいきょうのあるごりずむ
「さてテクニカル指標を勉強していくか」と思ったのですが、その前に素人のぼくはとても感覚的な(つまり根拠のない)アルゴリズムを思いついてしまいました。

## アルゴリズムの概要
いかなるアルゴリズムを使うにしても、損切が続くような(大きな損が続くような)アルゴリズムは、適用している銘柄に相性が良くないので、適用しないほうがいいのではないかと思いました。
そこで、損切が続くような銘柄は買わないようにするアルゴリズムを作成してみました。


## コード
Quantxでは、Pythonを用いてコードを書きます。私の書いたコードは以下のようなものです。
基本的にはsampleコードままなので、変更した部分で重要そうな部分を中心にコードを説明していきたいと思います。
#### initialize関数

```python 
ctx.localStorage['not_buy'] = set([])
 ```

適当な位置でctx.localStorageに、「以降購入しない銘柄」を入れておくsetを作っておきます。
ちなみにlocalStorageは次回以降にhandle_signals関数が呼び出される時も常に値が同じ(保存されている)ことが保証されています。詳しくは[ドキュメント](https://factory.quantx.io/handbook/ja/api.html#ctx)を参照してください。

### handle_signals関数
```python
if len(ctx.localStorage['not_buy']) >= 5:
    # for (sym,val) in ctx.portfolio.positions.items():
    ctx.localStorage['not_buy'] = set([])
    for sym in ctx.localStorage['not_buy']:
        sec = ctx.getSecurity(sym)
        ctx.logger.debug(sym)
        ctx.localStorage[sym]['count'] = 0
```
すべての銘柄を購入してしまった場合、initialize関数で定義したsetの中身をリセットします。
最初のifの条件式で7を指定しているのは銘柄の数です。(マジックナンバーはよくないのでここはなるべく早くどうにかします…)

```py
if returns < -0.03:
    sec = ctx.getSecurity(sym)
    sec.order(-val["amount"], comment="損切り(%f)" % returns)
    ctx.localStorage[sym]['count'] += 1
    if ctx.localStorage[sym]['count'] >= 2:
        ctx.localStorage['not_buy'].add(sym)
        ctx.logger.debug(sym + 'not buy')
    done_syms.add(sym)
elif returns > 0.05:
    sec = ctx.getSecurity(sym)
    sec.order(-val["amount"], comment="利益確定売(%f)" % returns)
    ctx.localStorage[sym]['count'] = 0
    done_syms.add(sym)
```
利益確定、損切りの条件についてはとりあえずサンプルコードと同じパラメータを利用しています。
この条件を満たしたら各銘柄について個別に持っているcountの値を変動させます。損をするようならcountは増え得をするなら減ります。

## 比較
サンプルと私が作成アルゴリズムの比較をします。
### 条件
損切りを経て購入するか否かを決定するアルゴリズムであるため、期間は長めに3年を設定しました。銘柄についてはサンプルコードのまま使っています。
### 結果
#### サンプルアルゴリズム
![image.png](https://qiita-image-store.s3.amazonaws.com/0/227269/f7866c7f-0afa-e6ab-8b23-6a28d3cdf505.png)

割といい感じに利益が出てくれました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/227269/b93d5cd8-b917-9955-2f12-0c2abf7fd0fa.png)

各銘柄の詳細な損益結果です。トヨタ自動車で大きな損失をしてしまっていることがわかると思います。

#### 今回作成したアルゴリズム
![image.png](https://qiita-image-store.s3.amazonaws.com/0/227269/fc9eac79-1eb6-341f-f61a-543d02ec229f.png)

パッと見た感じ結構良さげです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/227269/600f47dc-cc3a-bd9e-5254-9f2f58262e40.png)

各銘柄の詳細な損益結果です。サンプルのアルゴリズムと比べ、トヨタ自動車を始めとした銘柄で損失が小さくなっていることを確認できると思います。

# 今後の展望

- 利益確定売・損切りのパラメータ等をサンプルのまま利用しているので、より良い値がないか模索する。
- 「以降購入しない銘柄」に入ってる銘柄について、別のアルゴリズムが適用できないか検討する。
- 損を続ける銘柄に対しての処理だけを行っているが、得を続ける銘柄に対しても何かしらの処理を行えないかを検討する。
- もっと様々な銘柄に対してこのアルゴリズムを試してみる。

# 最後に
SmartTrade社では、毎週水曜日に勉強会を開催している他、アルゴリズム大会の説明会なども行っています。
https://python-algo.connpass.com/

# 参考
[QuantxのAPIドキュメント](https://factory.quantx.io/handbook/ja/api.html)