Skip to content

Commit da73558

Browse files
author
Fernando Fernandes
committed
Add short handling logic
1 parent ec459ee commit da73558

File tree

3 files changed

+57
-34
lines changed

3 files changed

+57
-34
lines changed

Sources/SwiftTrader/Model/Error/SwiftTraderError.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,11 @@ public enum SwiftTraderError: Error {
4848
/// The offsett has to be lower than the percentage of the profit; the order will not be placed.
4949
case kucoinInvalidOffset(offset: Double, profitPercentage: Double)
5050

51-
/// The target price is lower than the entry price; the order will not be placed.
52-
case kucoinInvalidTargetPrice(entryPrice: String, targetPrice: String)
51+
/// (`long` position) The target price is lower than the entry price; the order will not be placed.
52+
case kucoinInvalidTargetPriceLower(entryPrice: String, targetPrice: String)
53+
54+
/// (`short` position) The target price is higher than the entry price; the order will not be placed.
55+
case kucoinInvalidTargetPriceHigher(entryPrice: String, targetPrice: String)
5356

5457
/// And error ocurred while executing the function `SwiftTrader.kucoinFuturesOrderList(orderStatus:)`.
5558
case kucoinOrderList(error: Error)

Sources/SwiftTrader/Model/SwiftTraderOrderInput.swift

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,52 +12,58 @@ public struct SwiftTraderStopLimitOrderInput {
1212

1313
// MARK: - Properties
1414

15+
public let clean: Bool
16+
public let contractSymbol: String
17+
public let currentPrice: Double
18+
public let entryPrice: Double
1519
public let exchange: SwiftTraderExchange
20+
public let isLong: Bool
1621
public let ticker: String
1722
public let tickerSize: String
18-
public let contractSymbol: String
19-
public let entryPrice: Double
20-
public let currentPrice: Double
21-
public let profitPercentage: Double
2223
public let offset: Double
23-
public let clean: Bool
24+
public let profitPercentage: Double
2425

2526
// MARK: - Lifecycle
2627

2728
/// Creates a `SwiftTraderOrderInput` instance.
2829
///
2930
/// - Parameters:
31+
/// - clean: When `true`, all the untriggered stop orders for the `contractSymbol` will be cancelled before placing a new one.
32+
/// Cleaning is done via `SwiftTrader.kucoinFuturesCancelStopOrders(symbol:)`. In case that fails, the execution continues
33+
/// and a new order will be placed regardless.
34+
/// - contractSymbol: E.g.: XBTCUSDTM
35+
/// - currentPrice: The current price of the asset.
36+
/// - entryPrice: E.g.: "42.856", "43567.98", "127.01".
3037
/// - exchange: E.g.: Kucoin, Binance
38+
/// - isLong: Indicates the side of the position. `true` indicates "long". `false` indicates "short. The side is taken into consideration
39+
/// when performing trailing stop logic.
3140
/// - ticker: E.g.: BTCUSDT
3241
/// - tickerSize: E.g.: "1", "0.05", "0.00001"
33-
/// - contractSymbol: E.g.: XBTCUSDTM
34-
/// - entryPrice: E.g.: "42.856", "43567.98", "127.01".
35-
/// - currentPrice: The current price of the asset.
36-
/// - profitPercentage: The percentage of the profit at this point, e.g.: "1.5", "0.67".
3742
/// - offset: How far the **"target price"** of the stop order will be from the `currentPrice`. For example,
3843
/// suppose the `profitPercentage` is `1.0%` and the `offset` is `0.75%`. The stop order to be placed will be `0.25%`
3944
/// of the current price (`1.0%` - `0.75%`). Using the same `offset`, if the `profitPercentage` is now `2.0%`, the stop order
4045
/// will be placed at `1.25%` of the current price (`2.0%` - `0.75%`).
41-
/// - clean: When `true`, all the untriggered stop orders for the `contractSymbol` will be cancelled before placing a new one.
42-
/// Cleaning is done via `SwiftTrader.kucoinFuturesCancelStopOrders(symbol:)`. In case that fails, the execution continues
43-
/// and a new order will be placed regardless.
44-
public init(exchange: SwiftTraderExchange,
45-
ticker: String,
46-
tickerSize: String,
46+
/// - profitPercentage: The percentage of the profit at this point, e.g.: "1.5", "0.67".
47+
public init(clean: Bool,
4748
contractSymbol: String,
48-
entryPrice: Double,
4949
currentPrice: Double,
50-
profitPercentage: Double,
50+
entryPrice: Double,
51+
exchange: SwiftTraderExchange,
52+
isLong: Bool,
53+
ticker: String,
54+
tickerSize: String,
5155
offset: Double,
52-
clean: Bool) {
56+
profitPercentage: Double
57+
) {
58+
self.clean = clean
59+
self.contractSymbol = contractSymbol
60+
self.currentPrice = currentPrice
61+
self.entryPrice = entryPrice
5362
self.exchange = exchange
63+
self.isLong = isLong
5464
self.ticker = ticker
5565
self.tickerSize = tickerSize
56-
self.contractSymbol = contractSymbol
57-
self.entryPrice = entryPrice
58-
self.currentPrice = currentPrice
59-
self.profitPercentage = profitPercentage
6066
self.offset = offset
61-
self.clean = clean
67+
self.profitPercentage = profitPercentage
6268
}
6369
}

Sources/SwiftTrader/SwiftTrader+TrailingStop.swift

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,12 @@ public extension SwiftTrader {
4141
let priceIncrement: Double = input.entryPrice * targetPercentage
4242
logger.log("Price increment: \(priceIncrement.toDecimalString())")
4343

44-
// E.g.: 42000.69 + 2830.846506 = 44831.536506
45-
let targetPrice: Double = input.entryPrice + priceIncrement
44+
// "Long" example: 42000.69 + 2830.846506 = 44831.536506
45+
// "Short" example: 42000.69 - 2830.846506 = 39169.843494
46+
let targetPrice: Double = input.isLong ?
47+
input.entryPrice + priceIncrement :
48+
input.entryPrice - priceIncrement
49+
4650
logger.log("Entry price: \(input.entryPrice.toDecimalString())")
4751
logger.log("Target price: \(targetPrice.toDecimalString())")
4852

@@ -95,19 +99,29 @@ public extension SwiftTrader {
9599
logger.log("Ticker size: \(input.tickerSize)")
96100
logger.log("Target price string: \(targetPriceString)")
97101

98-
// Throw in case the target price became lower than the entry price for whatever reason.
99-
// Do not place an order in this scenario.
100-
guard Double(targetPriceString) ?? 0 > input.entryPrice else {
101-
throw SwiftTraderError.kucoinInvalidTargetPrice(
102-
entryPrice: input.entryPrice.toDecimalString(),
103-
targetPrice: targetPriceString)
102+
if input.isLong {
103+
guard Double(targetPriceString) ?? 0 > input.entryPrice else {
104+
// Long position: throw in case the target price became LOWER than the entry price
105+
// for whatever reason. Do not place an order in this scenario.
106+
throw SwiftTraderError.kucoinInvalidTargetPriceLower(
107+
entryPrice: input.entryPrice.toDecimalString(),
108+
targetPrice: targetPriceString)
109+
}
110+
} else {
111+
guard Double(targetPriceString) ?? 0 < input.entryPrice else {
112+
// Short position: throw in case the target price became HIGHER than the entry price
113+
// for whatever reason. Do not place an order in this scenario.
114+
throw SwiftTraderError.kucoinInvalidTargetPriceHigher(
115+
entryPrice: input.entryPrice.toDecimalString(),
116+
targetPrice: targetPriceString)
117+
}
104118
}
105119

106120
return KucoinOrderParameters(
107121
symbol: input.contractSymbol,
108122
side: .sell,
109123
type: .limit,
110-
stop: .down,
124+
stop: input.isLong ? .down : .up,
111125
stopPriceType: .TP,
112126
stopPrice: "\(targetPriceString)",
113127
price: "\(targetPriceString)",

0 commit comments

Comments
 (0)