見出し画像

bitflyer建玉自炊管理用プログラムコード with golang

1. 注文をした際は、order_idをkeyに辞書を作る、追加する(仮に保持辞書はorders, positionsとする
2. ws.executionsからorder_idで注文照会
3. orders[key]sizeが同サイズであれば、positionsに全追加①。sizeが違う場合部分約定としてws.exec.sizeをpositionsに登録、ordersにはws.exec.size分減らし上書き②
4. 以降部分約定は①で対応可能

※ 建玉自炊に関し、REST APIは一切叩いてないです。弊環境では一切ズレません。Python等の場合、io waitでブロックしている場合があるようなので、適宜childordersで答え合わせがいいのかもしれませんね。

// Check 注文建玉idをws.Executionで約定照会
// What: 注文後約定を建玉増減させし保持する
// Why: 建玉自炊のため
// e.g. 注文後、order_idをkeyに辞書に登録、流れてくるws.executionsで都度id照会、
//         部分約定はorders辞書に戻し一部positions辞書に登録に、完全約定はorders辞書から削除しpositionsにまるっと追加
// cf. 他プログラムでよく見るのは、部分約定時の登録漏れやズレ

func (p *OrderManager) Check(es []executions.Execution) {
	var wg sync.WaitGroup // 同実行用

	wg.Add(1)
	go func() { // Side別に同時実行
		defer wg.Done() // 終わったらworkgroupに終了報告

		for _, e := range es {
			sid := e.BuyChildOrderAcceptanceID
			v, isThereB := p.Orders.Load(sid) 
			if isThereB { // ws.Exec idが注文idにあった場合
				pos, isThere := p.Positions.Load(sid)
				if !isThere { // 建玉にデータがない場合
					o, ok := v.(Order) // 型チェック
					if !ok {
						continue
					}
					if o.Size == e.Size { // 注文枚数全約定なら
						p.Orders.Delete(sid)
						p.Total.Set(false, o) // 約定率算出用
						p.Positions.Store(sid, o)
					} else { // 部分約定なら注文を残しつつ、sizeを減らす
						o.Size -= e.Size
						p.Orders.Store(sid, o) // Orderは約定分減らしてset

						o.Size = e.Size
						p.Total.Set(false, o) // 約定率算出用
						p.Positions.Store(sid, o) // Positionsは約定した分でset
					}

					continue
				}

				// すでに建玉がある場合はsize追加
				po, ok := pos.(Order) // 型チェック
				if !ok {
					continue
				}
				po.Size += e.Size // 既存のものに約定を追加して再登録
				p.Total.Set(false, po)
				p.Positions.Store(sid, po)

				// 注文
				o, ok := v.(Order) // 型チェック
				if !ok {
					continue
				}

				if o.Size <= e.Size {
					p.Orders.Delete(sid)
				} else { // 部分約定なら戻す
					o.Size -= e.Size
					p.Orders.Store(sid, o)
				}
			}
		}
	}()

	wg.Add(1)
	go func() {
		defer wg.Done()

		for _, e := range es {
			sid := e.SellChildOrderAcceptanceID
			v, isThereS := p.Orders.Load(sid)
			if isThereS {
				pos, isThere := p.Positions.Load(sid)
				if !isThere { // 建玉にデータがない場合
					o, ok := v.(Order)
					if !ok {
						continue
					}
					if o.Size == e.Size { // 注文枚数全約定なら
						p.Orders.Delete(sid)
						p.Total.Set(false, o)
						p.Positions.Store(sid, o)
					} else { // 部分約定なら注文を残しつつ、sizeを減らす
						o.Size -= e.Size
						p.Orders.Store(sid, o) // Orderは約定分減らしてset

						o.Size = e.Size
						p.Total.Set(false, o)
						p.Positions.Store(sid, o) // Positionsは約定した分でset
					}

					continue
				}

				// すでに建玉がある場合はsize追加
				po, ok := pos.(Order)
				if !ok {
					continue
				}
				po.Size += e.Size
				p.Total.Set(false, po)
				p.Positions.Store(sid, po)

				// 注文
				o, ok := v.(Order)
				if !ok {
					continue
				}

				if o.Size <= e.Size {
					p.Orders.Delete(sid)
				} else { // 部分約定なら戻す
					o.Size -= e.Size
					p.Orders.Store(sid, o)
				}
			}
		}
	}()

	wg.Wait()
}

この記事が気に入ったらサポートをしてみませんか?