import { CashMarginTypeStrategy , NewOrderRequest , LeveragePosition } from './types' ; import BrokerApi from './BrokerApi' ; import { Order , OrderStatus , OrderSide , CashMarginType , OrderType } from '../types' ; import { eRound , almostEqual } from '../util' ; import * as _ from 'lodash' ; export default class NetOutStrategy implements CashMarginTypeStrategy { constructor ( private readonly brokerApi ) { } async send ( order ) { if ( order . cashMarginType !== CashMarginType . NetOut ) { throw new Error ( ) ; } const request = await this . getNetOutRequest ( order ) ; const reply = await this . brokerApi . newOrder ( request ) ; if ( ! reply . success ) { throw new Error ( 'Send failed.' ) ; } order . sentTime = reply . created_at ; order . status = OrderStatus . New ; order . brokerOrderId = reply . id ; order . lastUpdated = new Date ( ) ; } async getBtcPosition ( ) { const positions = await this . brokerApi . getAllOpenLeveragePositions ( ) ; const longPosition = _ . sumBy ( positions . filter ( p => p . side === 'buy' ) , p => p . amount ) ; const shortPosition = _ . sumBy ( positions . filter ( p => p . side === 'sell' ) , p => p . amount ) ; return eRound ( longPosition - shortPosition ) ; } private async getNetOutRequest ( order ) { const openPositions = await this . brokerApi . getAllOpenLeveragePositions ( ) ; const targetSide = order . side === OrderSide . Buy ? 'sell' : 'buy' ; const candidates = _ ( openPositions ) . filter ( p => p . side === targetSide ) . filter ( p => almostEqual ( p . amount , order . size , 1 ) ) . value ( ) ; if ( order . symbol !== 'BTC/JPY' ) { throw new Error ( 'Not supported' ) ; } const pair = 'btc_jpy' ; const rate = order . type === OrderType . Market ? undefined : order . price ; const request = { pair , rate } ; if ( candidates . length === 0 ) { return { ... request , order_type : order . side === OrderSide . Buy ? 'leverage_buy' : 'leverage_sell' , amount : order . size } ; } const targetPosition = _ . last ( candidates ) as LeveragePosition ; return { ... request , order_type : order . side === OrderSide . Buy ? 'close_short' : 'close_long' , amount : targetPosition . amount , position_id : Number ( targetPosition . id ) } ; } }