Skip to content

Positions Handling

Intro

When orders are executed and completed, the HaasScript engine will maintain internal bot positions. The positions will increase or decrease depending on the order direction executed. The engine will keep track of fee costs, unrealized and realized profits as well as the profit/loss. Once the position is closed, it will be stored and new one is created when an entry order has been completed.

HaasScript also offers the ability to separate positions based on an identifier. This functionality is only available when trading with the unmanaged commands.

Managed Trading

In managed trading, the bot is limited to one open position at a time. Once the position reaches the configured trade amount, no further entries are placed. When an exit signal arrives, the bot buys or sells until the position is fully closed.

Commands that accept an optional positionId (such as those in the Easy Insurance & Safeties, and Position Information categories) can leave it empty under managed trading — with only one position, the ID is redundant.

Partial Filled Orders

When a partially filled order completes, the filled amount is added to or subtracted from the position size — an entry adds, an exit subtracts. On the next signal, the bot opens or closes based on the actual filled amount. For example, if the trade amount is 1 BTC and an entry order was only filled for 0.3 BTC, the next entry signal will place an order for the remaining 0.7 BTC, while an exit signal will close the 0.3 BTC that was filled.

Unmanaged Trading

By default unmanaged trading script will also have a single position per market which will in- or decrease depending on the order direction. But you also have the ability to create multiple positions within a single script. This is very useful in scripts where tracking individual entries is necessary. By separating the positions we can easily keep track of the individual profit, size, calculate the stop loss or take profit price and much more.

Separating Positions

Creating separate positions can be done with the positionId parameter in the place order commands. We need to save and pass on a unique value for each position.

-- Let's create 2 new long positions
positionId1 = NewGuid()
positionId2 = NewGuid()
orderId1 = PlaceGoLongOrder(10000, TradeAmount(), {positionId = positionId1})
orderId2 = PlaceGoLongOrder(9500, TradeAmount(), {positionId = positionId2})

-- Save the id so we can use them later.
Save('positionId1', positionId1)
Save('positionId2', positionId2)
Save('orderId1', orderId1)
Save('orderId2', orderId2)

Requesting Information

Once our orders have been filled we can request information on those positions. Even though we have 1 position on the exchange with an average price of 9750, we have 2 separate positions internally. One with an enter price of 10.000 and one of 9.500.

positionId1 = Load('positionId1')
positionId2 = Load('positionId2')

enterPrice1 = GetPositionEnterPrice(positionId1) -- This will return 10000
enterPrice2 = GetPositionEnterPrice(positionId2) -- This will return 9500

Easy Safeties/Insurances

We can utilize the built-in safeties and insurances for each of the positions. With this we can, for example, keep track of 2 different TakeProfit levels.

positionId1 = Load('positionId1')
positionId2 = Load('positionId2')

position1StopLoss = TakeProfit(10, positionId1)
position2StopLoss = TakeProfit(2, positionId2)

Closing the Position

We can gracefully exit the position without known the exact amount. Using the PlaceExitPositionOrder in combination with the positionId allows you to easily close each position separately. This command supports both spot and margin/leverage trading.

positionId2 = Load('positionId2')
position2StopLoss = StopLoss(2, positionId2)
if position2StopLoss == true then
    PlaceExitPositionOrder(positionId2, {type = MarketOrderType})
end

Shorting Spot Markets

In unmanaged trading, a bot can go short even on spot markets. When a sell order completes and the bot has no buy position, it creates a sell position instead. Profits on the sell are realized when the bot buys back. The amount allocated to the sell position is excluded from any new buy position.

For example, with 1 BTC and 1000 USD in the wallet, and BTC at 1000 USD price (total wallet value: 2000 USD):

  1. Buy 1 BTC @ 1000 USD — A buy position of 1 BTC is opened at 1000 USD.
  2. Sell 2 BTC @ 2000 USD — The buy position of 1 BTC is sold (realized profit: 1000 USD). The remaining 1 BTC sold creates a sell position.
  3. Buy 2 BTC @ 1000 USD — The sell position of 1 BTC is bought back (realized profit: 1000 USD). The remaining 1 BTC bought opens a new buy position.

After this, the wallet holds 1 BTC and 3000 USD. At 1000 USD per BTC, the total wallet value is 4000 USD — a total profit of 2000 USD.