@@ -15,22 +15,74 @@ import Foundation
15
15
public extension SwiftTrader {
16
16
17
17
func createOrderParameters( for input: SwiftTraderOrderInput ) -> KucoinOrderParameters {
18
- let targetPercentage : Double = ( input. profitPercentage / 100 ) - ( input. offset / 100 )
18
+ logger. log ( " Creating order parameters... " )
19
+
20
+ // E.g: 7.47 -> 0.0747
21
+ let profitPercentage : Double = ( input. profitPercentage / 100 )
22
+ logger. log ( " Profit percentage: \( profitPercentage. toDecimalString ( ) ) " )
23
+
24
+ // Instead of creating an order with a fixed target percentage (say 0.025), add some fat to it (e.g.: 0.027)
25
+ let offsetMargin : Double = 0.02
26
+ logger. log ( " Offset margin: \( offsetMargin. toDecimalString ( ) ) " )
27
+
28
+ // E.g.: (0.75 - 0.02) / 100 = 0.0073, which translates to 0.0027 (0,27%)
29
+ let offset : Double = ( input. offset - offsetMargin) / 100
30
+ logger. log ( " Offset: \( offset. toDecimalString ( ) ) " )
31
+
32
+ // E.g.: (0.0747 - 0.0073) = 0.0674 (6,74%)
33
+ let targetPercentage : Double = profitPercentage - offset
34
+ logger. log ( " Target percentage: \( targetPercentage. toDecimalString ( ) ) " )
35
+
36
+ // E.g.: 42000.69 * 0.0674 = 2830.846506
19
37
let priceIncrement : Double = input. entryPrice * targetPercentage
38
+ logger. log ( " Price increment: \( priceIncrement. toDecimalString ( ) ) " )
39
+
40
+ // E.g.: 42000.9 + 2830.846506 = 44831.536506
41
+ let targetPrice : Double = input. entryPrice + priceIncrement
42
+ logger. log ( " Entry price: \( input. entryPrice. toDecimalString ( ) ) " )
43
+ logger. log ( " Target price: \( targetPrice. toDecimalString ( ) ) " )
44
+
45
+ // Now in order to avoid a huge difference between the entry price and the target price in terms of size,
46
+ // "normalize" them based on the entry price by first counting its characters.
47
+ let entryPriceCount = input. entryPrice. toDecimalString ( ) . count
48
+ logger. log ( " Entry price count: \( entryPriceCount) " )
49
+
50
+ // Count the target price characters too.
51
+ let targetPriceCount = targetPrice. toDecimalString ( ) . count
52
+ logger. log ( " Target price count: \( targetPriceCount) " )
53
+
54
+ // E.g.: 12 - 8 (44831.536506 - 42000.69)
55
+ // "44831.536506" becomes "44831.53".
56
+ let charactersToBeRemoved = abs ( targetPriceCount - entryPriceCount)
57
+ var targetPriceString = " \( targetPrice. toDecimalString ( ) ) " . dropLast ( charactersToBeRemoved)
58
+ logger. log ( " Target price normalize: \( targetPriceString) " )
59
+
60
+ // Finally, avoid the following Kucoin error with minimal effort: "The parameter shall be a multiple of ..."
61
+ // First, just try replacing the last character by "1". E.g.: "0.00002347" becomes "0.00002341"
62
+ if targetPriceString. components ( separatedBy: " . " ) . count > 1 {
63
+ targetPriceString = targetPriceString. dropLast ( ) + " 1 "
64
+ } else {
65
+ // Handles whole numbers: "3735" becomes "3735.1" (instead of "3731").
66
+ targetPriceString += " .1 "
67
+ }
68
+ logger. log ( " Target price string: \( targetPriceString) " )
20
69
21
- #warning("TODO: round up?")
22
- // Why Int? From a Kucoin response: "The parameter shall be a multiple of 1."
23
- let targetPrice = Int ( input. entryPrice + priceIncrement)
24
- let targetPriceString = String ( targetPrice)
70
+ // E.g.: "44831.53" becomes "44831".
71
+ // Workaround to not call "https://docs.kucoin.com/futures/#get-open-contract-list" (for now).
72
+ // "The price specified must be a multiple number of the contract tickSize, otherwise the system will report an
73
+ // error when you place the order. The tick size is the smallest price increment in which the prices are quoted.
74
+ if let priceDouble = Double ( targetPriceString) , priceDouble > 10 {
75
+ targetPriceString = " \( priceDouble. rounded ( . down) . toDecimalString ( ) ) "
76
+ }
25
77
26
78
return KucoinOrderParameters (
27
79
symbol: input. contractSymbol,
28
80
side: . sell,
29
81
type: . limit,
30
82
stop: . down,
31
83
stopPriceType: . TP,
32
- stopPrice: targetPriceString,
33
- price: targetPriceString,
84
+ stopPrice: " \( targetPriceString) " ,
85
+ price: " \( targetPriceString) " ,
34
86
reduceOnly: true ,
35
87
closeOrder: true
36
88
)
0 commit comments