保有数が0の場合の売り注文を回避する #QuantX

# order is ignored due to amount is 0
QuantXがバージョンアップしてからこんな警告が出るようになりました。
<img width="1365" alt="スクリーンショット 2019-10-10 17.29.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318447/a40f0319-3aa6-ccc9-4498-2dba1c623707.png">

警告文の一部を抜粋

```
2018-07-12 jp.stock.9984 order is ignored due to amount is 0.
```

保有数が0で売り注文を出してるから注文を無視するという警告文が出ています。
バックのシステムが無視してくれていますが、黄色い警告文が出ているので不安になります。
handle_signals関数下で処理して、警告文が出ないようにしたいと思います。

# 警告文が出る条件
色々試行錯誤してみた結果、以下の条件下で出るそうです。
## 1. 保有数が0で売り注文を出している。
QuantXは現時点ではロングでの入りしかできません（ショートから入ることはできません。）
つまり、保有数が0の時売却する株がないため売ることができないため。システムが自動的に取引を無視してくれます。

## 2. 株を購入する際、売買条件にあっていない。
例えば、株価2000円の株を単元株数買うと20万円必要になります。
ここで、金額指定を10万円に設定していたりするとシステムが自動的に取引を無視してくれます。

# 警告文はなるべく消したい。
システムが自動処理してくれるとはいえ、警告文が出るのはやはり嫌なものです。
上記の２に関してはアルゴリズム作成の際の銘柄選択にあった注文方法を選ぶのが早そうですが、1に関してはプログラムで解決できそうなので実装していきます。

# set型を使う
今回はPythonのset型を使い、ポジションを持っていない銘柄を判別していきます。
そもそもset型とは集合を扱うための型であり
・重複した要素がない
・要素に順番がない
という二つの特徴を持つ複数の値を格納できる型です。


#方針
方法はシンプルです。

1.portfolio_positionsにない銘柄をnone_symsと定義したset型に入れる。
2.portfolio_positions内でamountが0の銘柄をnone_symsと定義したset型に入れる。
3.売りシグナルのループ文でnone_symsに該当する銘柄があったらcontinueする。

# 実装
サンプルコードは以下のリンクから参照してください。
https://factory.quantx.io/developer/82025c466c0e451ea4f6cd6d3cd26abb

また銘柄によってはwarningは出ますが出ている理由としては株を購入する際、売買条件にあっていないためです。

handle_signals関数以下を記述します。

```python:
def handle_signals(ctx, date, current):
  '''
  current: pd.DataFrame
  '''
  #市況シグナル
  market_sig = current["market:sig"]
  #利益確定及び損切りを格納するset型
  done_syms = set([])
  #portfolio.positionsに存在しない銘柄を格納するset型
  none_syms = set([])
  
  #ログ出力（確認用 日付、市況シグナル、portfolio.positions）
  # ctx.logger.debug(date)
  # ctx.logger.debug(market_sig)
  # ctx.logger.debug(ctx.portfolio.positions.items())

  #portfolio.positionsに銘柄が存在するかのチェック
  for (sym, val) in market_sig.items():
    judge = sym in ctx.portfolio.positions
    if (judge == False):
      none_syms.add(sym)
  for (sym, val) in ctx.portfolio.positions.items():
    c_amounts = val["amount"]
    if (c_amounts == 0):
      none_syms.add(sym)
  
  # 損切り、利確の設定    
  for (sym, val) in ctx.portfolio.positions.items():
    returns = val["returns"]
    amounts = val["amount"]
    if returns < -0.04:
      sec = ctx.getSecurity(sym)
      sec.order(-val["amount"], comment="損切り(%f)" % returns)
      done_syms.add(sym)
    elif returns > 0.05:
      sec = ctx.getSecurity(sym)
      sec.order(-val["amount"], comment="利益確定売(%f)" % returns)
      done_syms.add(sym)
      
  #ログ出力（確認用 保有していない銘柄、保有している銘柄）
  # ctx.logger.debug(none_syms)
  # ctx.logger.debug(done_syms)
  
  # 買いシグナル
  buy = market_sig[market_sig > 0.0]
  for (sym, val) in buy.items():
    if sym in done_syms:
      continue
    sec = ctx.getSecurity(sym)
    sec.order(sec.unit() * 1, orderType=maron.OrderType.MARKET_OPEN, comment="SIGNAL BUY")
    # ctx.logger.debug("購入: %s,  %f" % (sec.code(), val))
    pass
  
  # 売りシグナル
  sell = market_sig[market_sig < 0.0]
  for (sym, val) in sell.items():
    if sym in done_syms:
      continue
    if sym in none_syms:
      continue
    sec = ctx.getSecurity(sym)
    sec.order_target(0,orderType=maron.OrderType.MARKET_OPEN, comment="SIGNAL SELL")
    # ctx.logger.debug("売却: %s,  %f" % (sec.code(), val))
    pass
```
これで保有していない銘柄に対して売り注文を執行しないようになりました。


# 終わりに
portfolio_positions等の銘柄情報でかなり色々なデータを取ることができるとわかりました。
次回はこの辺のQuantX独自APIについてまとめようかなと思います。


# 宣伝
##勉強会やってます！
日時：毎週金曜日19時〜
場所：神田　千代田共同ビル４階　SmartTrade社オフィス
内容：初心者(プログラミングってものを知らなくてもOK)向けに初心者(私とか)がこんな内容をハンズオン(一緒にやる事)で解説しています
備考：猛者の方も是非御鞭撻にいらして下さい、そして開発・伝導者になりましょう！

##もくもく会もやってます！
日時：毎週水曜日18時〜
場所：神田　千代田共同ビル４階　SmartTrade社オフィス
内容：基本黙々と自習しながら猛者の方に質問して強くなっていく会
備考：お菓子と終わりにお酒を飲みながら参加者と歓談できます！

##詳細はこちらです
週によっては開催されない週もあります。
また勉強会参加、もくもく会参加には基本的に事前に参加登録をしてください！
Pythonアルゴリズム勉強会HP：https://python-algo.connpass.com/
(connpassって言うイベントサイトに飛びます)

##ストアもあります
システムトレードの開発者が作ったアルゴリズムがQuantX Storeで販売されています！
詳細は以下のリンクから
https://quantx.io/

# 免責注意事項
このコードや購入したアルゴリズム及び知識を使った実際の取引で生じた損益に関しては一切の責任を負いかねますので御了承下さい