Skip to content

Commit

Permalink
support market order
Browse files Browse the repository at this point in the history
  • Loading branch information
bitrinjani committed Dec 16, 2017
1 parent 823ac17 commit f081d9e
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 12 deletions.
5 changes: 2 additions & 3 deletions src/Bitflyer/BrokerApi.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { hmac, nonce } from '../util';
import { hmac, nonce, safeQueryStringStringify } from '../util';
import WebClient from '../WebClient';
import {
SendChildOrderRequest, SendChildOrderResponse,
CancelChildOrderRequest, CancelChildOrderResponse, ChildOrdersParam,
ChildOrdersResponse, ExecutionsResponse, ExecutionsParam, Execution, BalanceResponse,
BoardResponse, ChildOrder, Balance
} from './types';
import * as querystring from 'querystring';

export default class BrokerApi {
private readonly baseUrl = 'https://api.bitflyer.jp';
Expand Down Expand Up @@ -75,7 +74,7 @@ export default class BrokerApi {
const method = 'GET';
let pathWithParam = path;
if (requestParam) {
const param = querystring.stringify(requestParam);
const param = safeQueryStringStringify(requestParam);
pathWithParam += `?${param}`;
}
return await this.call<R>(pathWithParam, method);
Expand Down
7 changes: 3 additions & 4 deletions src/Coincheck/BrokerApi.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as _ from 'lodash';
import { hmac, nonce } from '../util';
import { hmac, nonce, safeQueryStringStringify } from '../util';
import WebClient from '../WebClient';
import * as querystring from 'querystring';
import {
AccountsBalanceResponse, LeveragePositionsRequest, LeveragePositionsResponse,
LeveragePosition, OrderBooksResponse, NewOrderRequest, NewOrderResponse,
Expand Down Expand Up @@ -107,15 +106,15 @@ export default class BrokerApi {

private post<R, T>(path: string, requestBody: T): Promise<R> {
const method = 'POST';
const body = querystring.stringify(requestBody);
const body = safeQueryStringStringify(requestBody);
return this.call<R>(path, method, body);
}

private get<R, T = never>(path: string, requestParam?: T): Promise<R> {
const method = 'GET';
let pathWithParam = path;
if (requestParam) {
const param = querystring.stringify(requestParam);
const param = safeQueryStringStringify(requestParam);
pathWithParam += `?${param}`;
}
return this.call<R>(pathWithParam, method);
Expand Down
9 changes: 7 additions & 2 deletions src/Coincheck/NetOutStrategy.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { CashMarginTypeStrategy, NewOrderRequest, LeveragePosition } from './types';
import BrokerApi from './BrokerApi';
import Order from '../Order';
import { OrderStatus, OrderSide, CashMarginType } from '../types';
import { OrderStatus, OrderSide, CashMarginType, OrderType } from '../types';
import { eRound, almostEqual } from '../util';
import * as _ from 'lodash';

Expand Down Expand Up @@ -37,7 +37,12 @@ export default class NetOutStrategy implements CashMarginTypeStrategy {
.filter(p => p.side === targetSide)
.filter(p => almostEqual(p.amount, order.size, 1))
.value();
const request = { pair: 'btc_jpy', rate: order.price };
if (order.symbol !== 'BTCJPY') {
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,
Expand Down
5 changes: 2 additions & 3 deletions src/Quoine/BrokerApi.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { nonce } from '../util';
import { nonce, safeQueryStringStringify } from '../util';
import WebClient from '../WebClient';
import {
SendOrderResponse, SendOrderRequest, CancelOrderResponse,
OrdersResponse, TradingAccountsResponse, PriceLevelsResponse, TradingAccount,
CloseAllResponse,
ClosingTrade
} from './types';
import * as querystring from 'querystring';
import * as jwt from 'jsonwebtoken';

export default class BrokerApi {
Expand Down Expand Up @@ -77,7 +76,7 @@ export default class BrokerApi {
const method = 'GET';
let pathWithParam = path;
if (requestParam) {
const param = querystring.stringify(requestParam);
const param = safeQueryStringStringify(requestParam);
pathWithParam += `?${param}`;
}
return await this.call<R>(pathWithParam, method);
Expand Down
40 changes: 40 additions & 0 deletions src/__tests__/Coincheck/NetOutStrategy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,46 @@ describe('NetOutStrategy', () => {
expect(order.brokerOrderId).toBe('391697892');
});

test('netout market when no closable position', async () => {
const strategy = new NetOutStrategy(new BrokerApi('', ''));
const order = new Order(
Broker.Coincheck,
OrderSide.Sell,
0.01,
830000,
CashMarginType.NetOut,
OrderType.Market,
undefined
);
const request: NewOrderRequest = await strategy.getNetOutRequest(order);
expect(request.order_type).toBe('leverage_sell');
expect(request.amount).toBe(0.01);
expect(request.position_id).toBeUndefined();
expect(request.rate).toBeUndefined();
});

test('netout non BTCJPY', async () => {
const strategy = new NetOutStrategy(new BrokerApi('', ''));
const order = new Order(
Broker.Coincheck,
OrderSide.Sell,
0.01,
830000,
CashMarginType.NetOut,
OrderType.Limit,
undefined
);
order.symbol = 'ZZZJPY';
const fn = jest.fn();
try {
await strategy.getNetOutRequest(order);
expect(true).toBe(false);
} catch (ex) {
fn();
}
expect(fn.mock.calls.length).toBe(1);
});

afterAll(() => {
nock.restore();
});
Expand Down
6 changes: 6 additions & 0 deletions src/__tests__/util.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,10 @@ test('readJsonFileSync with no BOM', () => {

test('findBrokerConfig with no config', () => {
expect(() => util.findBrokerConfig({brokers: []}, Broker.Bitflyer)).toThrow();
});

test('safeQueryStringStringify', () => {
const o = { a: 1, b: undefined };
const result = util.safeQueryStringStringify(o);
expect(result).toBe('a=1');
});
6 changes: 6 additions & 0 deletions src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as _ from 'lodash';
import * as crypto from 'crypto';
import * as fs from 'fs';
import * as path from 'path';
import * as querystring from 'querystring';
import { ConfigRoot, Broker, BrokerConfig } from './types';

interface ToStringable {
Expand Down Expand Up @@ -92,4 +93,9 @@ export function findBrokerConfig(configRoot: ConfigRoot, broker: Broker): Broker
throw new Error(`Unabled to find ${broker} in config.`);
}
return found;
}

export function safeQueryStringStringify(o: any) {
const noUndefinedFields = _.pickBy(o, _.negate(_.isUndefined));
return querystring.stringify(noUndefinedFields);
}

0 comments on commit f081d9e

Please sign in to comment.