Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable short/long trades without exit of open trade #117

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/dict/exchange_position.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ const Position = require('./position');
module.exports = class ExchangePosition {
constructor(exchange, position) {
if (!(position instanceof Position)) {
throw 'TypeError: invalid position';
throw new Error(`TypeError: invalid position`);
}

this._exchange = exchange;
this._position = position;
}

getKey() {
return this._exchange + this._position.symbol;
return this._exchange + this._position.getSymbol() + this._position.getSide();
}

getExchange() {
Expand All @@ -23,6 +23,6 @@ module.exports = class ExchangePosition {
}

getSymbol() {
return this._position.symbol;
return this._position.getSymbol();
}
};
18 changes: 15 additions & 3 deletions src/dict/position.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
module.exports = class Position {
static get SIDE_LONG() {
return 'long';
}

static get SIDE_SHORT() {
return 'short';
}

/**
* @param symbol 'BTCUSD'
* @param side "long" or "short"
Expand All @@ -10,7 +18,7 @@ module.exports = class Position {
* @param raw
*/
constructor(symbol, side, amount, profit, updatedAt, entry, createdAt, raw = undefined) {
if (!['long', 'short'].includes(side)) {
if (![Position.SIDE_LONG, Position.SIDE_SHORT].includes(side)) {
throw new Error(`Invalid position direction given:${side}`);
}

Expand All @@ -33,11 +41,11 @@ module.exports = class Position {
}

isShort() {
return this.side === 'short';
return this.getSide() === Position.SIDE_SHORT;
}

isLong() {
return this.side === 'long';
return this.getSide() === Position.SIDE_LONG;
}

getAmount() {
Expand All @@ -56,6 +64,10 @@ module.exports = class Position {
return this.entry;
}

getSide() {
return this.side;
}

getCreatedAt() {
return this.createdAt;
}
Expand Down
12 changes: 10 additions & 2 deletions src/modules/pairs/pair_state_execution.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ module.exports = class PairStateExecution {
async onSellBuyPair(pairState) {
const position = await this.exchangeManager.getPosition(pairState.exchange, pairState.symbol);

if (position) {
if (position && position.getSide() === pairState.getState()) {
pairState.clear();
this.logger.debug(
`block ${pairState.getState()} order; open position:${JSON.stringify([pairState.exchange, pairState.symbol])}`
Expand All @@ -60,8 +60,12 @@ module.exports = class PairStateExecution {
])}`
);

if (position) {
// If we have open position and we want to switch short/long, we need to add position size to order size
pairState.options = pairState.options || {};
pairState.options.positionAmount = position.getAmount();
}
const exchangeOrder = await this.pairStateExecuteOrder(pairState);

if (exchangeOrder) {
if (exchangeOrder.shouldCancelOrderProcess()) {
// check if we need to to cancel the process
Expand Down Expand Up @@ -272,6 +276,10 @@ module.exports = class PairStateExecution {
return;
}

if (options.positionAmount) {
orderSize = parseFloat(orderSize) + Math.abs(options.positionAmount);
}

// inverse price for short
if (side === 'short') {
orderSize *= -1;
Expand Down
65 changes: 65 additions & 0 deletions test/modules/pairs/pair_state_execution.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,71 @@ describe('#pair state execution', function() {
assert.equal(myOrder.hasAdjustedPrice(), false);
});

it('test limit open order trigger for long when we have short position', async () => {
let myOrder;

const executor = new PairStateExecution(
undefined,
{
calculateOrderSizeCapital: () => {
return 1337;
}
},
{
executeOrder: (exchange, order) => {
myOrder = order;
return undefined;
}
},
undefined
);

await executor.pairStateExecuteOrder(
PairState.createLong('exchange', 'BTCUSD', OrderCapital.createAsset(1369), {positionAmount: -1337}, true, () => {})
);

assert.equal(myOrder.symbol, 'BTCUSD');
assert.equal(myOrder.side, 'long');
assert.equal(myOrder.price, undefined);
assert.equal(myOrder.amount, 1337*2);
assert.equal(myOrder.type, 'limit');
assert.equal(myOrder.options.post_only, true);
assert.equal(myOrder.hasAdjustedPrice(), true);
});


it('test limit open order trigger for short when we have long position', async () => {
let myOrder;

const executor = new PairStateExecution(
undefined,
{
calculateOrderSizeCapital: () => {
return 1337;
}
},
{
executeOrder: (exchange, order) => {
myOrder = order;
return undefined;
}
},
undefined
);

await executor.pairStateExecuteOrder(
PairState.createShort('exchange', 'BTCUSD', OrderCapital.createAsset(1369), {positionAmount: 1337}, true, () => {})
);

assert.equal(myOrder.symbol, 'BTCUSD');
assert.equal(myOrder.side, 'short');
assert.equal(myOrder.price, undefined);
assert.equal(myOrder.amount, -1337*2);
assert.equal(myOrder.type, 'limit');
assert.equal(myOrder.options.post_only, true);
assert.equal(myOrder.hasAdjustedPrice(), true);
});

it('test limit open order trigger for short', async () => {
let myOrder;

Expand Down