PageRenderTime 48ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/src/main/scala/com.coinmachine.ares/trade/future/FutureWaveCutter.scala

https://gitlab.com/coinmachine/ares
Scala | 199 lines | 163 code | 26 blank | 10 comment | 41 complexity | 441020f97fa7edba42be20bfe542f40c MD5 | raw file
  1. package com.coinmachine.ares.trade.future
  2. import com.alibaba.fastjson.{JSONObject, JSON}
  3. import com.coinmachine.ares.Logging
  4. import com.coinmachine.ares.trade.{Exchange, Order, Strategy, UserInfo}
  5. import com.coinmachine.ares.util.{StrategyUtil, MathUtil, LoopQuery}
  6. import org.apache.commons._
  7. import scala.collection.mutable
  8. /**
  9. * Created by bobo on 16/4/5.
  10. */
  11. class FutureWaveCutter(val user: UserInfo, val coinType: String = "ltc", val orderDistance: Float = 0.005f,
  12. val tradeUnit: Float = 1, val stopRiskRate: Float = 10,
  13. val stopPrice: Float = 5, val contractTypes: String = "this_week,next_week,quarter") extends Strategy with Logging {
  14. val upPlace = new mutable.Stack[Order]()
  15. val downPlace = new mutable.Stack[Order]()
  16. val symbol = coinType + "_usd"
  17. logInfo(toString)
  18. class RiskController extends Logging with Runnable {
  19. override def run(): Unit = {
  20. while(!shutDownFlag) {
  21. val userInfo = LoopQuery.futureUserInfo(user);
  22. val marketUserInfo = userInfo.getJSONObject(coinType)
  23. val accountRights = marketUserInfo.getFloat("account_rights")
  24. val keepDeposit = marketUserInfo.getFloat("keep_deposit")
  25. val profitReal = marketUserInfo.getFloat("profit_real")
  26. val profitUnreal = marketUserInfo.getFloat("profit_unreal")
  27. val riskRate = marketUserInfo.getFloat("risk_rate")
  28. logDebug(s"Account rights:$accountRights, KeepDeposit:$keepDeposit, ProfitReal:$profitReal, ProfitUnreal:$profitUnreal, RiskRate:$riskRate")
  29. if (riskRate < stopRiskRate) {
  30. logWarn(s"riskRate($riskRate) < stopRiskRate($stopRiskRate)")
  31. shutDownFlag = true
  32. System.exit(-1)
  33. } else {
  34. logDebug(s"riskRate($riskRate) >= stopRiskRate($stopRiskRate)")
  35. }
  36. // contractTypes.split(",").foreach(ct => {
  37. // val futurePosition = LoopQuery.futurePosition(user, coinType + "_" + "usd", ct)
  38. // val forceLiquPrice = futurePosition.getFloat("force_liqu_price")
  39. // if (forceLiquPrice < stopPrice) {
  40. // logWarn("")
  41. // }
  42. // })
  43. Thread.sleep(100)
  44. }
  45. }
  46. }
  47. override def init(): Unit = {
  48. new Thread(new RiskController).start()
  49. Thread.sleep(2000)
  50. val ticker = LoopQuery.futureTicker(user, symbol, "quarter")
  51. val lastPrice = ticker.getFloat("last")
  52. logInfo(s"Ticker:$ticker")
  53. placeUpDownOrders(upPlace, downPlace, lastPrice)
  54. }
  55. def placeUpDownOrders(upPlace: mutable.Stack[Order], downPlace: mutable.Stack[Order], price: Float): Unit = {
  56. val downOrderPrice = ((math floor (price - orderDistance) * 1000) / 1000).toFloat
  57. if (!downPlace.exists(o => o.price == downOrderPrice)) {
  58. val orderId = LoopQuery.placeFutureOrder(user, symbol, "quarter", downOrderPrice, tradeUnit, "4")
  59. downPlace.push(new Order(orderId, downOrderPrice))
  60. Thread.sleep(20L)
  61. logInfo(s"Place an close_short order:$orderId with price:$downOrderPrice and amount:$tradeUnit")
  62. } else {
  63. logInfo(s"Already placed an close_short order with price:" + downOrderPrice)
  64. }
  65. val upOrderPrice = ((math floor (price + orderDistance) * 1000) / 1000).toFloat
  66. if (!upPlace.exists(o => o.price == upOrderPrice)) {
  67. val orderId = LoopQuery.placeFutureOrder(user, coinType + "_usd", "quarter", upOrderPrice, tradeUnit, "2")
  68. upPlace.push(new Order(orderId, upOrderPrice))
  69. Thread.sleep(20L)
  70. logInfo(s"Place an short order:$orderId with price:$upOrderPrice and amount:$tradeUnit")
  71. } else {
  72. logInfo(s"Already placed an short order with price:" + upOrderPrice)
  73. }
  74. }
  75. def processDeals() = {
  76. try {
  77. if (upPlace.nonEmpty) {
  78. val order = upPlace.top
  79. logDebug("Top Order of upPlace:" + order)
  80. val orderInfo = LoopQuery.futureOrderInfo(user, symbol, "quarter", order.id)
  81. Option(orderInfo.getIntValue("status")) match {
  82. case Some(oi) =>
  83. Option(orderInfo.getIntValue("status")) match {
  84. case Some(x) if x == -1 => //already canceled,被人工取消了理应再放一次
  85. upPlace.pop()
  86. case Some(x) if x == 2 => //totally concluded
  87. upPlace.pop()
  88. val price = orderInfo.getFloatValue("price")
  89. placeUpDownOrders(upPlace, downPlace, price)
  90. case _ =>
  91. }
  92. case None =>
  93. logError(s"Can't get order info for $order")
  94. }
  95. } else {
  96. logWarn(s"upPlace is empty.$upPlace")
  97. }
  98. if (downPlace.nonEmpty) {
  99. val order = downPlace.top
  100. val orderInfo = LoopQuery.futureOrderInfo(user, symbol, "quarter", order.id)
  101. Option(orderInfo) match {
  102. case Some(oi) =>
  103. Option(orderInfo.getIntValue("status")) match {
  104. case Some(x) if x == -1 =>
  105. downPlace.pop()
  106. case Some(x) if x == 2 =>
  107. downPlace.pop()
  108. val price = orderInfo.getFloatValue("price")
  109. placeUpDownOrders(upPlace, downPlace, price)
  110. case _ =>
  111. }
  112. case None =>
  113. logError(s"Can't get order info for $order")
  114. }
  115. } else {
  116. logWarn(s"downPlace is empty:$downPlace")
  117. }
  118. } catch {
  119. case e: Exception =>
  120. logError("Exception when placing order", e)
  121. }
  122. Thread.sleep(100)
  123. }
  124. override def run(): Unit = {
  125. init()
  126. while (!shutDownFlag) {
  127. processDeals()
  128. }
  129. }
  130. override def toString = s"FutureWaveCutter(symbol=$symbol, coinType=$coinType, orderDistance=$orderDistance, tradeUnit=$tradeUnit, stopRiskRate=$stopRiskRate, stopPrice=$stopPrice, contractTypes=$contractTypes)"
  131. }
  132. object FutureWaveCutter extends Logging {
  133. def main(args: Array[String]) {
  134. val (userInfo, coinType, distance, unit, srr): (UserInfo, String, Float, Float, Float) = {
  135. if (args.length > 0) {
  136. val parser: cli.CommandLineParser = new cli.DefaultParser
  137. val options: cli.Options = {
  138. val opts = new cli.Options
  139. opts.addOption("btc", false, "Trade in BTC Future Market, Other wise LTC Future Market")
  140. opts.addOption("d", true, "Order distance")
  141. opts.addOption("unit", true, "TradeUnit")
  142. opts.addOption("srr", true, "Stop Risk Rate")
  143. opts.addOption("apikey", true, "API Key")
  144. opts.addOption("secretkey", true, "Secret Key")
  145. opts
  146. }
  147. try {
  148. val cmdLine = parser.parse(options, args)
  149. val coinType: String = if (cmdLine.hasOption("btc")) "btc" else "ltc"
  150. val distance: Float = if (cmdLine.hasOption("d")) {
  151. cmdLine.getOptionValue("d").toFloat
  152. } else if (coinType == "ltc") 0.1f else 1
  153. val unit: Float = if (cmdLine.hasOption("unit")) cmdLine.getOptionValue("unit").toFloat else if (coinType == "ltc") 1 else 0.1f
  154. val srr: Float = if (cmdLine.hasOption("srr")) cmdLine.getOptionValue("srr").toFloat else 10.0f
  155. val apiKey: String = if (cmdLine.hasOption("apikey")) cmdLine.getOptionValue("apikey") else throw new IllegalArgumentException("API key not giving.")
  156. val secretKey: String = if (cmdLine.hasOption("secretkey")) cmdLine.getOptionValue("secretkey") else throw new IllegalArgumentException("Secret key not giving.")
  157. (new UserInfo(apiKey, secretKey, Exchange.OKCOINCOM_FUTURE), coinType, distance, unit, srr)
  158. } catch {
  159. case e: Exception =>
  160. logError(s"Error:$e")
  161. val formatter: cli.HelpFormatter = new cli.HelpFormatter
  162. formatter.printHelp("FutureWaveCutter", options)
  163. System.exit(-1)
  164. (null, "ltc", 0.1f, 0.1f, 100)
  165. }
  166. } else {
  167. StrategyUtil.config()
  168. }
  169. }
  170. val wc = new FutureWaveCutter(userInfo, coinType = coinType, orderDistance = distance, tradeUnit = unit, stopRiskRate = srr)
  171. new Thread(wc).run()
  172. }
  173. }