├── strategy ├── src │ └── main │ │ ├── resources │ │ ├── store.json │ │ ├── config.json │ │ └── grid.json │ │ └── java │ │ └── com │ │ └── zyf │ │ └── strategy │ │ ├── triplefilter │ │ └── SingleState.java │ │ ├── Main.java │ │ ├── Strategy.java │ │ ├── rsi │ │ ├── RsiState.java │ │ └── Timer.java │ │ └── GridStrategy.java ├── strategy.iml ├── target │ └── classes │ │ ├── com │ │ └── zyf │ │ │ └── strategy │ │ │ ├── Main.class │ │ │ └── Strategy.class │ │ └── config.json └── pom.xml ├── logo.png ├── easyquant.iml ├── framework ├── framework.iml ├── target │ ├── test-classes │ │ └── com │ │ │ └── zyf │ │ │ └── framework │ │ │ ├── Test.class │ │ │ └── Strategy.class │ └── classes │ │ ├── com │ │ └── zyf │ │ │ └── framework │ │ │ ├── boot │ │ │ ├── Environment.class │ │ │ ├── BaseStrategy.class │ │ │ └── ApplicationContext.class │ │ │ ├── util │ │ │ ├── StopWatch.class │ │ │ └── StopWatch$TaskInfo.class │ │ │ ├── EasyQuantyApplication.class │ │ │ └── scheduling │ │ │ ├── ScheduledJob.class │ │ │ ├── ScheduledTask.class │ │ │ ├── ScheduleTaskManager.class │ │ │ └── interfaces │ │ │ └── ScheduledByZyf.class │ │ └── config.json ├── src │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── zyf │ │ │ └── framework │ │ │ ├── Test.java │ │ │ └── Strategy.java │ └── main │ │ ├── resources │ │ └── config.json │ │ └── java │ │ └── com │ │ └── zyf │ │ └── framework │ │ ├── service │ │ ├── IEmailService.java │ │ └── impl │ │ │ └── EmailServiceImpl.java │ │ ├── scheduling │ │ ├── interfaces │ │ │ └── ScheduledByZyf.java │ │ ├── ScheduledJob.java │ │ ├── ScheduleTaskManager.java │ │ └── ScheduledTask.java │ │ ├── boot │ │ ├── Environment.java │ │ └── BaseStrategy.java │ │ ├── util │ │ └── FileUtil.java │ │ └── EasyQuantyApplication.java └── pom.xml ├── common ├── target │ └── classes │ │ ├── com │ │ └── zyf │ │ │ └── common │ │ │ ├── model │ │ │ ├── Asset.class │ │ │ ├── Depth.class │ │ │ ├── Header.class │ │ │ ├── Kline.class │ │ │ ├── Level.class │ │ │ ├── Order.class │ │ │ ├── Ticker.class │ │ │ ├── Trade.class │ │ │ ├── Account.class │ │ │ ├── Balance.class │ │ │ ├── BaseData.class │ │ │ ├── Precision.class │ │ │ ├── enums │ │ │ │ ├── Role.class │ │ │ │ ├── Side.class │ │ │ │ ├── State.class │ │ │ │ ├── Type.class │ │ │ │ ├── DealType.class │ │ │ │ ├── HttpMethod.class │ │ │ │ └── ExchangeEnum.class │ │ │ ├── future │ │ │ │ ├── Index.class │ │ │ │ ├── Instrument.class │ │ │ │ ├── BitMEXInstrument.class │ │ │ │ ├── Instrument$Type.class │ │ │ │ ├── Instrument$Settle.class │ │ │ │ └── Instrument$OptionType.class │ │ │ ├── InstrumentTrade.class │ │ │ └── http │ │ │ │ └── HttpParameter.class │ │ │ ├── util │ │ │ ├── MhUtil.class │ │ │ ├── YamlUtil.class │ │ │ ├── EhcacheUtil.class │ │ │ └── BigDecimalUtil.class │ │ │ ├── crypto │ │ │ ├── HexUtil.class │ │ │ ├── HmacType.class │ │ │ └── HmacUtil.class │ │ │ ├── http │ │ │ └── HttpUtil.class │ │ │ ├── exceptions │ │ │ ├── ErrorCode.class │ │ │ ├── EHAErrorCodeEnum.class │ │ │ ├── ExTimeOutException.class │ │ │ └── ExchangeHttpApiException.class │ │ │ └── okhttp │ │ │ ├── OkHttpV3Client.class │ │ │ └── OkHttpV3ClientProxy.class │ │ └── log4j.properties ├── src │ └── main │ │ └── java │ │ └── com │ │ └── zyf │ │ └── common │ │ ├── exceptions │ │ ├── ExTimeOutException.java │ │ ├── ErrorCode.java │ │ ├── EHAErrorCodeEnum.java │ │ └── ExchangeHttpApiException.java │ │ ├── model │ │ ├── Header.java │ │ ├── enums │ │ │ ├── SecuritiesTypeEnum.java │ │ │ ├── HttpMethod.java │ │ │ ├── Offset.java │ │ │ ├── State.java │ │ │ ├── Role.java │ │ │ ├── ExchangeEnum.java │ │ │ ├── Type.java │ │ │ ├── Side.java │ │ │ └── DealType.java │ │ ├── BaseData.java │ │ ├── Level.java │ │ ├── Precision.java │ │ ├── option │ │ │ ├── OptionDetailInfo.java │ │ │ └── Instrument.java │ │ ├── Account.java │ │ ├── future │ │ │ ├── Index.java │ │ │ ├── InstrumentFut.java │ │ │ └── BitMEXInstrument.java │ │ ├── Balance.java │ │ ├── Depth.java │ │ ├── Ticker.java │ │ ├── Kline.java │ │ ├── Trade.java │ │ ├── Position.java │ │ ├── InstrumentTrade.java │ │ ├── Order.java │ │ ├── Asset.java │ │ └── http │ │ │ └── HttpParameter.java │ │ ├── crypto │ │ ├── HmacType.java │ │ ├── HexUtil.java │ │ └── HmacUtil.java │ │ ├── util │ │ ├── MhUtil.java │ │ ├── RepeatUtil.java │ │ ├── MathUtil.java │ │ ├── YamlUtil.java │ │ ├── DateUtil.java │ │ └── BigDecimalUtil.java │ │ ├── okhttp │ │ └── OkHttpV3ClientProxy.java │ │ └── http │ │ └── HttpUtil.java └── pom.xml ├── baseservice ├── target │ └── classes │ │ └── com │ │ └── zyf │ │ └── baseservice │ │ ├── IExchange.class │ │ ├── util │ │ ├── okex │ │ │ ├── OkexUtil.class │ │ │ └── OkexSignUtil.class │ │ ├── deribit │ │ │ ├── DeribitUtil.class │ │ │ └── DeribitTradeUtil.class │ │ └── huobipro │ │ │ ├── HuobiProUtil.class │ │ │ └── HuobiProSignUtil.class │ │ └── model │ │ └── enums │ │ └── CacheNameEnum.class ├── src │ └── main │ │ ├── java │ │ └── com │ │ │ └── zyf │ │ │ └── baseservice │ │ │ ├── model │ │ │ └── enums │ │ │ │ └── CacheNameEnum.java │ │ │ ├── util │ │ │ ├── FieldUtil.java │ │ │ └── okex │ │ │ │ └── OkexSignUtil.java │ │ │ └── IMdExchange.java │ │ └── resources │ │ └── logback.xml └── pom.xml ├── trade ├── target │ └── classes │ │ └── com │ │ └── zyf │ │ └── trade │ │ ├── proxy │ │ └── TradeExchangeProxy.class │ │ └── factory │ │ └── TradeExchangeFactory.class ├── src │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── zyf │ │ │ └── trade │ │ │ ├── TradeExchangeApplication.java │ │ │ ├── factory │ │ │ └── TradeExchangeFactory.java │ │ │ └── proxy │ │ │ └── TradeExchangeProxy.java │ └── test │ │ └── java │ │ └── com │ │ └── zyf │ │ └── trade │ │ └── HuobiProTest.java └── pom.xml ├── .idea ├── $CACHE_FILE$ ├── $PRODUCT_WORKSPACE_FILE$ ├── encodings.xml ├── compiler.xml ├── misc.xml └── inspectionProfiles │ └── Project_Default.xml ├── marketdata ├── target │ └── classes │ │ └── com │ │ └── zyf │ │ └── marketdata │ │ ├── proxy │ │ └── MdExchangeProxy.class │ │ ├── factory │ │ └── MdExchangeFactory.class │ │ └── http │ │ └── option │ │ └── deribit │ │ └── DeribitMdExchange.class ├── src │ └── main │ │ └── java │ │ └── com │ │ └── zyf │ │ └── marketdata │ │ ├── MarketDataApplication.java │ │ ├── factory │ │ └── MdExchangeFactory.java │ │ ├── proxy │ │ └── MdExchangeProxy.java │ │ └── http │ │ ├── stock │ │ ├── OkexMdExchange.java │ │ └── HuobiProMdExchange.java │ │ └── option │ │ └── HuobiProMdOptionExchange.java └── pom.xml └── pom.xml /strategy/src/main/resources/store.json: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/logo.png -------------------------------------------------------------------------------- /easyquant.iml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /framework/framework.iml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /strategy/strategy.iml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /strategy/target/classes/com/zyf/strategy/Main.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/strategy/target/classes/com/zyf/strategy/Main.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/model/Asset.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/model/Asset.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/model/Depth.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/model/Depth.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/model/Header.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/model/Header.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/model/Kline.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/model/Kline.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/model/Level.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/model/Level.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/model/Order.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/model/Order.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/model/Ticker.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/model/Ticker.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/model/Trade.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/model/Trade.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/util/MhUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/util/MhUtil.class -------------------------------------------------------------------------------- /strategy/target/classes/com/zyf/strategy/Strategy.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/strategy/target/classes/com/zyf/strategy/Strategy.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/crypto/HexUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/crypto/HexUtil.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/http/HttpUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/http/HttpUtil.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/model/Account.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/model/Account.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/model/Balance.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/model/Balance.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/model/BaseData.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/model/BaseData.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/util/YamlUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/util/YamlUtil.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/crypto/HmacType.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/crypto/HmacType.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/crypto/HmacUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/crypto/HmacUtil.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/model/Precision.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/model/Precision.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/model/enums/Role.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/model/enums/Role.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/model/enums/Side.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/model/enums/Side.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/model/enums/State.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/model/enums/State.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/model/enums/Type.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/model/enums/Type.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/util/EhcacheUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/util/EhcacheUtil.class -------------------------------------------------------------------------------- /framework/target/test-classes/com/zyf/framework/Test.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/framework/target/test-classes/com/zyf/framework/Test.class -------------------------------------------------------------------------------- /baseservice/target/classes/com/zyf/baseservice/IExchange.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/baseservice/target/classes/com/zyf/baseservice/IExchange.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/model/future/Index.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/model/future/Index.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/util/BigDecimalUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/util/BigDecimalUtil.class -------------------------------------------------------------------------------- /framework/target/test-classes/com/zyf/framework/Strategy.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/framework/target/test-classes/com/zyf/framework/Strategy.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/exceptions/ErrorCode.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/exceptions/ErrorCode.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/model/InstrumentTrade.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/model/InstrumentTrade.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/model/enums/DealType.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/model/enums/DealType.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/model/enums/HttpMethod.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/model/enums/HttpMethod.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/okhttp/OkHttpV3Client.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/okhttp/OkHttpV3Client.class -------------------------------------------------------------------------------- /framework/target/classes/com/zyf/framework/boot/Environment.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/framework/target/classes/com/zyf/framework/boot/Environment.class -------------------------------------------------------------------------------- /framework/target/classes/com/zyf/framework/util/StopWatch.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/framework/target/classes/com/zyf/framework/util/StopWatch.class -------------------------------------------------------------------------------- /trade/target/classes/com/zyf/trade/proxy/TradeExchangeProxy.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/trade/target/classes/com/zyf/trade/proxy/TradeExchangeProxy.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/model/enums/ExchangeEnum.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/model/enums/ExchangeEnum.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/model/future/Instrument.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/model/future/Instrument.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/model/http/HttpParameter.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/model/http/HttpParameter.class -------------------------------------------------------------------------------- /framework/target/classes/com/zyf/framework/boot/BaseStrategy.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/framework/target/classes/com/zyf/framework/boot/BaseStrategy.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/exceptions/EHAErrorCodeEnum.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/exceptions/EHAErrorCodeEnum.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/okhttp/OkHttpV3ClientProxy.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/okhttp/OkHttpV3ClientProxy.class -------------------------------------------------------------------------------- /framework/target/classes/com/zyf/framework/EasyQuantyApplication.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/framework/target/classes/com/zyf/framework/EasyQuantyApplication.class -------------------------------------------------------------------------------- /trade/target/classes/com/zyf/trade/factory/TradeExchangeFactory.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/trade/target/classes/com/zyf/trade/factory/TradeExchangeFactory.class -------------------------------------------------------------------------------- /.idea/$CACHE_FILE$: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /baseservice/target/classes/com/zyf/baseservice/util/okex/OkexUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/baseservice/target/classes/com/zyf/baseservice/util/okex/OkexUtil.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/exceptions/ExTimeOutException.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/exceptions/ExTimeOutException.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/model/future/BitMEXInstrument.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/model/future/BitMEXInstrument.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/model/future/Instrument$Type.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/model/future/Instrument$Type.class -------------------------------------------------------------------------------- /framework/target/classes/com/zyf/framework/boot/ApplicationContext.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/framework/target/classes/com/zyf/framework/boot/ApplicationContext.class -------------------------------------------------------------------------------- /framework/target/classes/com/zyf/framework/scheduling/ScheduledJob.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/framework/target/classes/com/zyf/framework/scheduling/ScheduledJob.class -------------------------------------------------------------------------------- /framework/target/classes/com/zyf/framework/util/StopWatch$TaskInfo.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/framework/target/classes/com/zyf/framework/util/StopWatch$TaskInfo.class -------------------------------------------------------------------------------- /marketdata/target/classes/com/zyf/marketdata/proxy/MdExchangeProxy.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/marketdata/target/classes/com/zyf/marketdata/proxy/MdExchangeProxy.class -------------------------------------------------------------------------------- /baseservice/target/classes/com/zyf/baseservice/util/okex/OkexSignUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/baseservice/target/classes/com/zyf/baseservice/util/okex/OkexSignUtil.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/model/future/Instrument$Settle.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/model/future/Instrument$Settle.class -------------------------------------------------------------------------------- /framework/target/classes/com/zyf/framework/scheduling/ScheduledTask.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/framework/target/classes/com/zyf/framework/scheduling/ScheduledTask.class -------------------------------------------------------------------------------- /baseservice/target/classes/com/zyf/baseservice/util/deribit/DeribitUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/baseservice/target/classes/com/zyf/baseservice/util/deribit/DeribitUtil.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/model/future/Instrument$OptionType.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/model/future/Instrument$OptionType.class -------------------------------------------------------------------------------- /marketdata/target/classes/com/zyf/marketdata/factory/MdExchangeFactory.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/marketdata/target/classes/com/zyf/marketdata/factory/MdExchangeFactory.class -------------------------------------------------------------------------------- /baseservice/target/classes/com/zyf/baseservice/model/enums/CacheNameEnum.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/baseservice/target/classes/com/zyf/baseservice/model/enums/CacheNameEnum.class -------------------------------------------------------------------------------- /baseservice/target/classes/com/zyf/baseservice/util/huobipro/HuobiProUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/baseservice/target/classes/com/zyf/baseservice/util/huobipro/HuobiProUtil.class -------------------------------------------------------------------------------- /common/target/classes/com/zyf/common/exceptions/ExchangeHttpApiException.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/common/target/classes/com/zyf/common/exceptions/ExchangeHttpApiException.class -------------------------------------------------------------------------------- /framework/target/classes/com/zyf/framework/scheduling/ScheduleTaskManager.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/framework/target/classes/com/zyf/framework/scheduling/ScheduleTaskManager.class -------------------------------------------------------------------------------- /baseservice/target/classes/com/zyf/baseservice/util/deribit/DeribitTradeUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/baseservice/target/classes/com/zyf/baseservice/util/deribit/DeribitTradeUtil.class -------------------------------------------------------------------------------- /baseservice/target/classes/com/zyf/baseservice/util/huobipro/HuobiProSignUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/baseservice/target/classes/com/zyf/baseservice/util/huobipro/HuobiProSignUtil.class -------------------------------------------------------------------------------- /framework/target/classes/com/zyf/framework/scheduling/interfaces/ScheduledByZyf.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/framework/target/classes/com/zyf/framework/scheduling/interfaces/ScheduledByZyf.class -------------------------------------------------------------------------------- /marketdata/src/main/java/com/zyf/marketdata/MarketDataApplication.java: -------------------------------------------------------------------------------- 1 | //package com.zyf.marketdata; 2 | // 3 | //public class MarketDataApplication { 4 | // public static void main(String[] args) { 5 | // } 6 | //} 7 | -------------------------------------------------------------------------------- /marketdata/target/classes/com/zyf/marketdata/http/option/deribit/DeribitMdExchange.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nashse/easy-quant/HEAD/marketdata/target/classes/com/zyf/marketdata/http/option/deribit/DeribitMdExchange.class -------------------------------------------------------------------------------- /framework/src/test/java/com/zyf/framework/Test.java: -------------------------------------------------------------------------------- 1 | package com.zyf.framework; 2 | 3 | public class Test { 4 | public static void main(String[] args) { 5 | String[] args1 = {"--config-name:config.json"}; 6 | EasyQuantyApplication.run(com.zyf.framework.Strategy.class, args1); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /trade/src/main/java/com/zyf/trade/TradeExchangeApplication.java: -------------------------------------------------------------------------------- 1 | //package com.zyf.trade; 2 | // 3 | //import lombok.extern.slf4j.Slf4j; 4 | // 5 | //@Slf4j 6 | //public class TradeExchangeApplication { 7 | // 8 | // public static void main(String[] args) { 9 | // 10 | // } 11 | //} 12 | // 13 | // 14 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/exceptions/ExTimeOutException.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.exceptions; 2 | 3 | /** 4 | * 交易所连接超过异常 5 | * @author yuanfeng.z 6 | * @date 2019/7/11 15:40 7 | */ 8 | public class ExTimeOutException extends RuntimeException { 9 | public ExTimeOutException(String msg) { 10 | super(msg); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/Header.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | /** 7 | * 数据头部信息 8 | * @author yuanfeng.z 9 | * @date 2019/10/24 10:59 10 | */ 11 | @Setter 12 | @Getter 13 | public class Header { 14 | 15 | /** 16 | * 路由键 17 | */ 18 | protected String routeKey; 19 | } 20 | -------------------------------------------------------------------------------- /strategy/src/main/resources/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "configs" : [ 3 | { 4 | "id" : "1", 5 | "exchangeName" : "deribit", 6 | "symbol" : "BTC-PERPETUAL", 7 | "mdE" : { "exchangeName" : "deribit" }, 8 | "tradeE" : { "exchangeName" : "deribit", "accessKey" : "accessKey/12312", "secretKey" : "secretKey" }, 9 | "huobiproE" : { "exchangeName" : "huobipro" } 10 | } 11 | ] 12 | } -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/exceptions/ErrorCode.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 错误码接口 3 | */ 4 | package com.zyf.common.exceptions; 5 | 6 | /** 7 | * 错误码接口 8 | * @author yuanfeng.z 9 | * @date 2019/6/25 10:27 10 | */ 11 | public interface ErrorCode { 12 | 13 | /** 14 | * 获取错误码 15 | * @return 16 | */ 17 | String getCode(); 18 | 19 | /** 20 | * 获取错误信息 21 | * @return 22 | */ 23 | String getDescription(); 24 | } -------------------------------------------------------------------------------- /framework/target/classes/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "configs" : [ 3 | { 4 | "id" : "1", 5 | "exchangeName" : "deribit", 6 | "symbol" : "BTC-PERPETUAL", 7 | "mdE" : { "exchangeName" : "deribit", "securitiesType" : "future" }, 8 | "tradeE" : { "exchangeName" : "deribit","securitiesType" : "future", "accessKey" : "accessKey/12312", "secretKey" : "secretKey" }, 9 | "huobiproE" : { "exchangeName" : "huobipro" }, 10 | "profit" : "12" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /framework/src/main/resources/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "configs" : [ 3 | { 4 | "id" : "1", 5 | "exchangeName" : "deribit", 6 | "symbol" : "BTC-PERPETUAL", 7 | "mdE" : { "exchangeName" : "deribit", "securitiesType" : "future" }, 8 | "tradeE" : { "exchangeName" : "deribit","securitiesType" : "future", "accessKey" : "accessKey/12312", "secretKey" : "secretKey" }, 9 | "huobiproE" : { "exchangeName" : "huobipro" }, 10 | "profit" : "12" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /strategy/src/main/java/com/zyf/strategy/triplefilter/SingleState.java: -------------------------------------------------------------------------------- 1 | package com.zyf.strategy.triplefilter; 2 | 3 | /** 4 | * 信号状态 5 | * @author yuanfeng.z 6 | * @date 2020/9/8 17:16 7 | */ 8 | public enum SingleState { 9 | 10 | LONG("long"), 11 | SHORT("short"), 12 | NOT_SINGLE("notSignle"); 13 | 14 | private String value; 15 | 16 | SingleState(String value) { 17 | this.value = value; 18 | } 19 | 20 | public String getValue() { 21 | return value; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/enums/SecuritiesTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model.enums; 2 | 3 | /** 4 | * 证券类型 5 | * 6 | * @author yuanfeng.z 7 | * @date 2020/7/29 21:44 8 | */ 9 | public enum SecuritiesTypeEnum { 10 | STOCK("stock"), 11 | FUTURE("future"), 12 | OPTION("option"); 13 | 14 | private String value; 15 | 16 | SecuritiesTypeEnum(String value) { 17 | this.value = value; 18 | } 19 | 20 | public String getValue() { 21 | return value; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /baseservice/src/main/java/com/zyf/baseservice/model/enums/CacheNameEnum.java: -------------------------------------------------------------------------------- 1 | package com.zyf.baseservice.model.enums; 2 | 3 | /** 4 | * 缓存名称枚举 5 | * @author yuanfeng.z 6 | * @date 2019/7/11 11:53 7 | */ 8 | public enum CacheNameEnum { 9 | TICKER("ticker"), 10 | DEPTH("depth"), 11 | KLINE("kline"); 12 | 13 | private String value; 14 | 15 | CacheNameEnum(String value) { 16 | this.value = value; 17 | } 18 | 19 | public String getValue() { 20 | return value; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/enums/HttpMethod.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model.enums; 2 | 3 | /** 4 | * Http请求方法 5 | * @author yuanfeng.z 6 | * @date 2019/6/29 12:14 7 | */ 8 | public enum HttpMethod { 9 | 10 | GET("GET"), 11 | 12 | PUT("PUT"), 13 | 14 | POST("POST"), 15 | 16 | DELETE("DELETE"); 17 | 18 | private String value; 19 | 20 | HttpMethod(String value) { 21 | this.value = value; 22 | } 23 | 24 | public String getValue() { 25 | return value; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /.idea/$PRODUCT_WORKSPACE_FILE$: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 1.8 8 | 9 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/enums/Offset.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model.enums; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | 5 | /** 6 | * "open":开 "close":平 7 | * 8 | * @author yuanfeng.z 9 | * @date 2019/6/29 10:30 10 | */ 11 | public enum Offset { 12 | 13 | /** 14 | * 买 15 | */ 16 | OPEN("open"), 17 | 18 | /** 19 | * 卖 20 | */ 21 | CLOSE("close"); 22 | 23 | 24 | private String value; 25 | 26 | Offset(String value) { 27 | this.value = value; 28 | } 29 | 30 | public String getValue() { 31 | return value; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/crypto/HmacType.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.crypto; 2 | 3 | /** 4 | * Hmac加密类型 5 | * 6 | * @author yuanfeng.z 7 | * @version 1.0 8 | * @date 2019-06-27 9 | */ 10 | public enum HmacType { 11 | 12 | HMAC_MD5("HmacMD5"), 13 | HMAC_SHA1("HmacSHA1"), 14 | HMAC_SHA256("HmacSHA256"), 15 | HMAC_SHA384("HmacSHA384"), 16 | HMAC_SHA512("HmacSHA512"); 17 | 18 | private String name; 19 | 20 | HmacType(String value) { 21 | this.name = value; 22 | } 23 | 24 | public String getName() { 25 | return name; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /strategy/src/main/resources/grid.json: -------------------------------------------------------------------------------- 1 | { 2 | "configs" : [ 3 | { 4 | "id" : "1", 5 | "exchangeName" : "okexv3", 6 | "symbol" : "MNBTC-USDT-SWAP", 7 | "mdE" : { "exchangeName" : "okexv3", "securitiesType" : "future" }, 8 | "tradeE" : { "exchangeName" : "okexv3", "securitiesType" : "future", 9 | "accessKey" : "xxx-xxx-xxx-xxx-xxx/xxxxx", "secretKey" : "xxx" }, 10 | "profit" : "12", 11 | "bInit" : 0, 12 | "storeFile" : "store.json", 13 | "host" : "xxx", 14 | "fromMail" : "xxx", 15 | "user" : "xxx", 16 | "password" : "xxx", 17 | "toMail" : "xxx" 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /strategy/src/main/java/com/zyf/strategy/Main.java: -------------------------------------------------------------------------------- 1 | package com.zyf.strategy; 2 | 3 | import com.zyf.framework.EasyQuantyApplication; 4 | 5 | /** 6 | * 策略主入口 7 | * 8 | * @author yuanfeng.z 9 | * @date 2020/7/27 19:15 10 | */ 11 | public class Main { 12 | public static void main(String[] args) throws ClassNotFoundException { 13 | // args[0] = "com.zyf.strategy.OkexGridStrategy"; 14 | // args[1] = "--config-name:grid.json"; 15 | // String[] argss = new String[2]; 16 | // argss[0] = "com.zyf.strategy.OkexGridStrategy"; 17 | // argss[1] = "--config-name:grid.json"; 18 | EasyQuantyApplication.run(Class.forName(args[0]), args[1]); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/BaseData.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * 基础数据类 10 | * @author yuanfeng.z 11 | * @date 2019/10/17 10:20 12 | */ 13 | @Setter 14 | @Getter 15 | public class BaseData implements Serializable { 16 | 17 | protected static final long serialVersionUID = 1L; 18 | 19 | /** 20 | * 交易所名称 21 | */ 22 | protected String exchangeName; 23 | 24 | /** 25 | * 合约id 26 | */ 27 | protected String instrumentId; 28 | 29 | /** 30 | * 头部信息 31 | */ 32 | protected Header header; 33 | } 34 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /framework/src/main/java/com/zyf/framework/service/IEmailService.java: -------------------------------------------------------------------------------- 1 | package com.zyf.framework.service; 2 | 3 | import java.util.List; 4 | 5 | public interface IEmailService { 6 | // void sendSimpleEmail(List sendToList, List ccList, String subject, String content); 7 | 8 | // void sendAttachmentsMail(List sendToList, List ccList, String subject, String content, String filePath); 9 | 10 | // void sendInlineResourceMail(List sendToList, List ccList, String subject, String content, String rscPath, String rscId); 11 | 12 | // Boolean sendHtmlMail(List sendToList, List ccList, String subject, String content); 13 | 14 | // Boolean sendThymeleafEmail(List sendToList, List ccList, String subject, String content); 15 | } 16 | -------------------------------------------------------------------------------- /strategy/src/main/java/com/zyf/strategy/Strategy.java: -------------------------------------------------------------------------------- 1 | package com.zyf.strategy; 2 | 3 | import com.zyf.framework.boot.BaseStrategy; 4 | import com.zyf.framework.scheduling.interfaces.ScheduledByZyf; 5 | import com.zyf.marketdata.proxy.MdExchangeProxy; 6 | import lombok.extern.slf4j.Slf4j; 7 | 8 | /** 9 | * 策略类demo 10 | * @author yuanfeng.z 11 | * @date 2020/7/27 1:44 12 | */ 13 | @Slf4j 14 | public class Strategy extends BaseStrategy { 15 | 16 | @Override 17 | protected void init() { 18 | 19 | } 20 | 21 | @Override 22 | protected void recovery() { 23 | 24 | } 25 | 26 | @Override 27 | @ScheduledByZyf(cron = "0/1 * * * * ?") 28 | protected void run() { 29 | log.info(this.toString()); 30 | log.info(mdE.getDepth(this.symbol).toString()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/enums/State.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model.enums; 2 | 3 | /** 4 | * 订单状态 5 | * @author yuanfeng.z 6 | * @date 2019/6/29 11:06 7 | */ 8 | public enum State { 9 | 10 | /** 11 | * 已提交 12 | */ 13 | SUBMIT(0), 14 | /** 15 | * 已成交 16 | */ 17 | FILLED(1), 18 | /** 19 | * 已取消 20 | */ 21 | CANCEL(2), 22 | /** 23 | * 部分成交 24 | */ 25 | PARTIAL(3), 26 | /** 27 | * 订单被拒绝 28 | */ 29 | REJECTED(4), 30 | /** 31 | * 止损单 32 | */ 33 | STOP(5);; 34 | 35 | private Integer value; 36 | 37 | State(Integer value) { 38 | this.value = value; 39 | } 40 | 41 | public Integer getValue() { 42 | return this.value; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /framework/src/main/java/com/zyf/framework/scheduling/interfaces/ScheduledByZyf.java: -------------------------------------------------------------------------------- 1 | package com.zyf.framework.scheduling.interfaces; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * 定时任务注解 7 | * @author yuanfeng.z 8 | * @date 2020/7/27 3:07 9 | */ 10 | @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Documented 13 | public @interface ScheduledByZyf { 14 | String CRON_DISABLED = "-"; 15 | 16 | String cron() default ""; 17 | 18 | String zone() default ""; 19 | 20 | long fixedDelay() default -1L; 21 | 22 | String fixedDelayString() default ""; 23 | 24 | long fixedRate() default -1L; 25 | 26 | String fixedRateString() default ""; 27 | 28 | long initialDelay() default -1L; 29 | 30 | String initialDelayString() default ""; 31 | } 32 | -------------------------------------------------------------------------------- /strategy/target/classes/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "configs" : [ 3 | { 4 | "id" : "1", 5 | "exchangeName" : "deribit", 6 | "symbol" : "BTC-PERPETUAL", 7 | "mdE" : { "exchangeName" : "deribit" }, 8 | "tradeE" : { "exchangeName" : "deribit", "accessKey" : "accessKey/12312", "secretKey" : "secretKey" }, 9 | "huobiproE" : { "exchangeName" : "huobipro" }, 10 | "profit" : "12" 11 | } 12 | ] 13 | } 14 | 15 | { 16 | "configs" : [ 17 | { 18 | "id" : "1", 19 | "exchangeName" : "huobipro", 20 | "symbol" : "BTC/USD", 21 | "mdE" : { "exchangeName" : "huobipro", "securitiesType" : "future" }, 22 | "tradeE" : { "exchangeName" : "huobipro", "securitiesType" : "future", "accessKey" : "51b2391e-uymylwhfeg-ac0468b8-d176f", "secretKey" : "b6cff0bb-dbd7fab8-1dfe9d30-4a9d7" }, 23 | "profit" : "12" 24 | } 25 | ] 26 | } -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/Level.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model; 2 | 3 | import lombok.Getter; 4 | import lombok.NoArgsConstructor; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | import java.io.Serializable; 9 | import java.math.BigDecimal; 10 | 11 | /** 12 | * 深度档位(价格、数量) 13 | * 14 | * @author yuanfeng.z 15 | * @date 2019/6/25 17:34 16 | */ 17 | @Setter 18 | @Getter 19 | @ToString 20 | @NoArgsConstructor 21 | public class Level implements Serializable { 22 | private static final long serialVersionUID = -7201349313159184470L; 23 | /** 24 | * 价格 25 | */ 26 | private BigDecimal price; 27 | /** 28 | * 数量 29 | */ 30 | private BigDecimal quantity; 31 | 32 | public Level(BigDecimal price, BigDecimal quantity) { 33 | this.price = price; 34 | this.quantity = quantity; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/util/MhUtil.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.util; 2 | 3 | import java.util.UUID; 4 | 5 | /** 6 | * uuid 7 | * @author yuanfeng.z 8 | * @date 2020/7/27 16:09 9 | */ 10 | public class MhUtil { 11 | 12 | /** 13 | * 获得指定数目的UUID 14 | * @param number int 需要获得的UUID数量 15 | * @return String[] UUID数组 16 | */ 17 | public static String[] getUUID(int number){ 18 | if(number < 1){ 19 | return null; 20 | } 21 | String[] retArray = new String[number]; 22 | for(int i=0;i R repeat(T t, Function func, int frequency) { 13 | while (frequency != 0) { 14 | try { 15 | return func.apply(t); 16 | } catch (Exception e) { 17 | frequency--; 18 | } 19 | } 20 | return null; 21 | } 22 | 23 | public static R repeat(T t, Function func) { 24 | int frequency = 2; 25 | while (frequency != 0) { 26 | try { 27 | return func.apply(t); 28 | } catch (Exception e) { 29 | frequency--; 30 | } 31 | } 32 | return null; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /baseservice/src/main/java/com/zyf/baseservice/util/FieldUtil.java: -------------------------------------------------------------------------------- 1 | package com.zyf.baseservice.util; 2 | 3 | /** 4 | * 字段工具类 5 | * @author yuanfeng.z 6 | * @date 2020/9/19 22:07 7 | */ 8 | public class FieldUtil { 9 | 10 | /** 11 | * 买卖 12 | * @param buySell buy sell 13 | * @return 14 | */ 15 | public static int buySell(String buySell) { 16 | if ("buy".equals(buySell)) { 17 | return 1; 18 | } else if ("sell".equals(buySell)) { 19 | return -1; 20 | } else { 21 | throw new RuntimeException(); 22 | } 23 | } 24 | 25 | /** 26 | * 看涨看跌 27 | * @param callPut P、C 28 | * @return 29 | */ 30 | public static int callPut(String callPut) { 31 | if ("P".equals(callPut)) { 32 | return -1; 33 | } else if ("C".equals(callPut)) { 34 | return 1; 35 | } else { 36 | throw new RuntimeException(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/enums/Role.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model.enums; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | 5 | /** 6 | * 合约角色 7 | * 8 | * @author god 9 | * @date 2019-12-23 10 | */ 11 | public enum Role { 12 | 13 | /** 14 | * taker 15 | */ 16 | TAKER("TAKER"), 17 | 18 | /** 19 | * maker 20 | */ 21 | MAKER("MAKER"); 22 | 23 | 24 | private String value; 25 | 26 | Role(String value) { 27 | this.value = value; 28 | } 29 | 30 | public String getValue() { 31 | return value; 32 | } 33 | 34 | public static Role getByValue(String type) { 35 | if (StrUtil.isBlank(type)) { 36 | return null; 37 | } 38 | else if(TAKER.value.equals(type)){ 39 | return TAKER; 40 | } 41 | else if(MAKER.value.equals(type)){ 42 | return MAKER; 43 | } 44 | return null; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/Precision.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model; 2 | 3 | import lombok.Getter; 4 | import lombok.ToString; 5 | 6 | /** 7 | * 币对精度 8 | * @author yuanfeng.z 9 | * @date 2019/6/26 10:54 10 | */ 11 | @Getter 12 | @ToString 13 | public class Precision { 14 | 15 | /** 16 | * 原始数据,以防定义字段不够用 17 | */ 18 | private final String originData; 19 | 20 | /** 21 | * 币对 22 | */ 23 | private final String symbol; 24 | 25 | /** 26 | * 左边货币精度(BTC/USDT -> BTC精度) 27 | */ 28 | private final Integer lPrecision; 29 | 30 | /** 31 | * 右边货币精度(BTC/USDT -> USDT精度) 32 | */ 33 | private final Integer rPrecision; 34 | 35 | public Precision(String originData, String symbol, Integer lPrecision, Integer rPrecision) { 36 | this.originData = originData; 37 | this.symbol = symbol; 38 | this.lPrecision = lPrecision; 39 | this.rPrecision = rPrecision; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /strategy/src/main/java/com/zyf/strategy/rsi/RsiState.java: -------------------------------------------------------------------------------- 1 | package com.zyf.strategy.rsi; 2 | 3 | import com.zyf.common.model.enums.ExchangeEnum; 4 | 5 | /** 6 | * rsi状态类 7 | * @author yuanfeng.z 8 | * @date 2020/8/18 17:37 9 | */ 10 | public class RsiState { 11 | 12 | public enum State { 13 | PREPARE("prepare"), 14 | MIDDLE("middle"), 15 | FINISH("finish"); 16 | 17 | private String value; 18 | 19 | State(String value) { 20 | this.value = value; 21 | } 22 | 23 | public String getValue() { 24 | return value; 25 | } 26 | } 27 | 28 | private State state = State.PREPARE; 29 | 30 | public void setState(State s) { 31 | state = s; 32 | // if (State.PREPARE.equals(state)) { 33 | // state = State.MIDDLE; 34 | // } else if (State.MIDDLE.equals(state)) { 35 | // state = State.FINISH; 36 | // } 37 | } 38 | 39 | public State getState() { 40 | return state; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /baseservice/src/main/java/com/zyf/baseservice/IMdExchange.java: -------------------------------------------------------------------------------- 1 | package com.zyf.baseservice; 2 | 3 | import com.zyf.common.model.*; 4 | import com.zyf.common.model.enums.Side; 5 | 6 | import java.math.BigDecimal; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | /** 11 | * 行情交易所接口 12 | *
公有接口 13 | * @author yuanfeng.z 14 | * @date 2019/6/28 15:33 15 | */ 16 | public interface IMdExchange { 17 | /** 18 | * 获取ticker 19 | * 20 | * @param symbol 币对 21 | * @return 22 | */ 23 | Ticker getTicker(String symbol); 24 | 25 | /** 26 | * 获取kline 27 | * 28 | * @param symbol 币对 29 | * @param granularity 级别 30 | * @return 31 | */ 32 | List getKline(String symbol, String granularity); 33 | 34 | /** 35 | * 获取深度 36 | * 37 | * @param symbol 币对 38 | * @return 39 | */ 40 | Depth getDepth(String symbol); 41 | 42 | /** 43 | * 获取精度 44 | * 45 | * @return 46 | */ 47 | Map getPrecisions(); 48 | } 49 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/option/OptionDetailInfo.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model.option; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.ToString; 6 | 7 | import java.math.BigDecimal; 8 | 9 | /** 10 | * 期权合约详细类 11 | * @author yuanfeng.z 12 | * @date 2020/9/14 22:50 13 | */ 14 | @Data 15 | @AllArgsConstructor 16 | public class OptionDetailInfo { 17 | private String originData; 18 | private String symbol; 19 | private String tradePartition; 20 | private String contractType; 21 | private String optionRightType; 22 | private String contractCode; 23 | private BigDecimal ivLastPrice; 24 | private BigDecimal ivAskOne; 25 | private BigDecimal ivBidOne; 26 | private BigDecimal ivMarkPrice; 27 | private BigDecimal delta; 28 | private BigDecimal gamma; 29 | private BigDecimal theta; 30 | private BigDecimal vega; 31 | private BigDecimal askOne; 32 | private BigDecimal bidOne; 33 | private BigDecimal lastPrice; 34 | private BigDecimal markPrice; 35 | } 36 | -------------------------------------------------------------------------------- /framework/src/test/java/com/zyf/framework/Strategy.java: -------------------------------------------------------------------------------- 1 | package com.zyf.framework; 2 | 3 | import com.zyf.framework.boot.BaseStrategy; 4 | import com.zyf.framework.scheduling.interfaces.*; 5 | import com.zyf.marketdata.proxy.MdExchangeProxy; 6 | import lombok.extern.slf4j.Slf4j; 7 | 8 | import java.math.BigDecimal; 9 | 10 | /** 11 | * 策略类demo 12 | * @author yuanfeng.z 13 | * @date 2020/7/27 1:44 14 | */ 15 | @Slf4j 16 | public class Strategy extends BaseStrategy { 17 | 18 | private String profit; 19 | 20 | private MdExchangeProxy huobiproE; 21 | 22 | @Override 23 | protected void recovery() { 24 | 25 | } 26 | 27 | @Override 28 | protected void init() { 29 | 30 | } 31 | 32 | @Override 33 | @ScheduledByZyf(cron = "0/1 * * * * ?") 34 | //@ScheduledByZyf(initialDelay = 20000, fixedDelay = 2000) 35 | protected void run() { 36 | log.info(this.toString()); 37 | log.info(mdE.getDepth(this.symbol).toString()); 38 | try { 39 | Thread.sleep(6000); 40 | } catch (InterruptedException e) { 41 | e.printStackTrace(); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/Account.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.ToString; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * 币对账户信息类 11 | * @author yuanfeng.z 12 | * @date 2019/6/28 11:37 13 | */ 14 | @Getter 15 | @ToString 16 | @EqualsAndHashCode 17 | public class Account implements Serializable { 18 | private static final long serialVersionUID = 1806860024261444247L; 19 | 20 | /** 21 | * 原始数据,以防定义字段不够用 22 | */ 23 | private final String originData; 24 | 25 | /** 26 | * 币对 27 | */ 28 | private final String symbol; 29 | 30 | /** 31 | * 左币种账户信息 32 | */ 33 | private final Balance lCurrency; 34 | 35 | /** 36 | * 右币种账户信息 37 | */ 38 | private final Balance rCurrency; 39 | 40 | 41 | public Account(String originData, String symbol, Balance lCurrency, Balance rCurrency) { 42 | this.originData = originData; 43 | this.symbol = symbol; 44 | this.lCurrency = lCurrency; 45 | this.rCurrency = rCurrency; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/future/Index.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model.future; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.ToString; 6 | 7 | import java.math.BigDecimal; 8 | import java.util.Date; 9 | 10 | /** 11 | * 指数类 12 | * @author yuanfeng.z 13 | * @date 2019/7/19 9:59 14 | */ 15 | @Getter 16 | @EqualsAndHashCode 17 | @ToString 18 | public class Index { 19 | 20 | /** 21 | * 时间戳("2018-08-20T03:44:50.000Z") 22 | */ 23 | private Date timestamp; 24 | 25 | /** 26 | * 合约("BTCUSD") 27 | */ 28 | private String symbol; 29 | 30 | /** 31 | * 指数合约(".BXBT") 32 | */ 33 | private String indexSymbol; 34 | 35 | /** 36 | * "BSTP" 37 | */ 38 | private String reference; 39 | 40 | /** 41 | * 收盘价格 42 | */ 43 | private BigDecimal closePrice; 44 | 45 | /** 46 | * 47 | */ 48 | private BigDecimal price; 49 | 50 | /** 51 | * 权重(0.5) 52 | */ 53 | private BigDecimal weight; 54 | 55 | /** 56 | * 57 | */ 58 | private Date logged; 59 | } 60 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/enums/ExchangeEnum.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model.enums; 2 | 3 | /** 4 | * 交易所枚举类 5 | * @author yuanfeng.z 6 | * @date 2019/6/25 15:25 7 | */ 8 | public enum ExchangeEnum { 9 | BHEX("bhex"), 10 | OKEXV3("okexv3"), 11 | HUOBIPRO("huobipro"), 12 | BINANCE("binance"), 13 | EMEX("emex"), 14 | HKSTOX("hkstox"), 15 | BITMEX("bitmex"), 16 | DERIBIT("deribit"), 17 | BIBOX("bibox"), 18 | COINEX("coinex"), 19 | FTX("ftx"), 20 | COINBENE("coinbene"), 21 | COINEX_PERPETUAL("coinex_perpetual"), 22 | GATEIO("gateio"), 23 | CRYPTO("crypto"), 24 | NULL("null"); 25 | 26 | private String value; 27 | 28 | ExchangeEnum(String value) { 29 | this.value = value; 30 | } 31 | 32 | public String getValue() { 33 | return value; 34 | } 35 | 36 | public static ExchangeEnum getEnum(String exchange){ 37 | for (ExchangeEnum e : ExchangeEnum.values()) { 38 | if(e.getValue().equals(exchange)){ 39 | return e; 40 | } 41 | } 42 | return ExchangeEnum.NULL; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/enums/Type.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model.enums; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | 5 | /** 6 | * 订单类型 7 | * @author yuanfeng.z 8 | * @date 2019/6/29 10:30 9 | */ 10 | public enum Type { 11 | 12 | /** 13 | * 市价 14 | */ 15 | MARKET("MARKET"), 16 | 17 | /** 18 | * 限价 19 | */ 20 | LIMIT("LIMIT"), 21 | 22 | LIQUIDATION("LIQUIDATION"), 23 | 24 | STOP_MARKET("STOP_MARKET"); 25 | 26 | private String value; 27 | 28 | Type(String value) { 29 | this.value = value; 30 | } 31 | 32 | public String getValue() { 33 | return value; 34 | } 35 | 36 | public static Type getByValue(String type) { 37 | if (StrUtil.isBlank(type)) { 38 | return null; 39 | } 40 | else if(MARKET.value.equals(type)){ 41 | return MARKET; 42 | } 43 | else if(LIMIT.value.equals(type)){ 44 | return LIMIT; 45 | } 46 | else if(LIQUIDATION.value.equals(type)){ 47 | return LIQUIDATION; 48 | } 49 | return null; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/Balance.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.ToString; 6 | 7 | import java.io.Serializable; 8 | import java.math.BigDecimal; 9 | 10 | /** 11 | * 币种账户信息类 12 | * @author yuanfeng.z 13 | * @date 2019/6/28 11:37 14 | */ 15 | @Getter 16 | @ToString 17 | @EqualsAndHashCode 18 | public class Balance implements Serializable { 19 | private static final long serialVersionUID = 1806860024261444247L; 20 | 21 | /** 22 | * 原始数据,以防定义字段不够用 23 | */ 24 | private final String originData; 25 | 26 | /** 27 | * 币种 28 | */ 29 | private final String currency; 30 | 31 | /** 32 | * 可用资金 33 | */ 34 | private final BigDecimal available; 35 | 36 | /** 37 | * 冻结资金 38 | */ 39 | private final BigDecimal frozen; 40 | 41 | 42 | public Balance(String originData, String currency, BigDecimal available, BigDecimal frozen) { 43 | this.originData = originData; 44 | this.currency = currency; 45 | this.available = available; 46 | this.frozen = frozen; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /framework/src/main/java/com/zyf/framework/scheduling/ScheduledJob.java: -------------------------------------------------------------------------------- 1 | package com.zyf.framework.scheduling; 2 | 3 | import org.quartz.*; 4 | 5 | import java.lang.reflect.InvocationTargetException; 6 | import java.lang.reflect.Method; 7 | 8 | /** 9 | * 定时任务job 10 | *
不会同时执行多个任务 11 | * @author yuanfeng.z 12 | * @date 2020/7/25 1:33 13 | */ 14 | @DisallowConcurrentExecution 15 | public class ScheduledJob implements Job { 16 | 17 | @Override 18 | public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { 19 | JobDetail jobDetail = jobExecutionContext.getJobDetail(); 20 | JobDataMap jobDataMap = jobDetail.getJobDataMap(); 21 | Method method = (Method)jobDataMap.get(ScheduledTask.METHOD); 22 | Object strategyIns = jobDataMap.get(ScheduledTask.STRATEGYINS); 23 | 24 | try { 25 | method.invoke(strategyIns); 26 | } catch (IllegalAccessException e) { 27 | throw new RuntimeException(e.getMessage()); 28 | } catch (InvocationTargetException e) { 29 | throw new RuntimeException(e.getMessage()); 30 | } catch (Exception e) { 31 | throw new RuntimeException(e.getMessage()); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /strategy/src/main/java/com/zyf/strategy/rsi/Timer.java: -------------------------------------------------------------------------------- 1 | package com.zyf.strategy.rsi; 2 | 3 | import java.util.concurrent.Executors; 4 | import java.util.concurrent.ScheduledExecutorService; 5 | import java.util.concurrent.TimeUnit; 6 | 7 | /** 8 | * 定时器 9 | * @author yuanfeng.z 10 | * @date 2020/8/26 8:18 11 | */ 12 | public class Timer { 13 | 14 | private ScheduledExecutorService exec; 15 | 16 | /** 17 | * 倒数计数器(分钟) 18 | */ 19 | private int count = 0; 20 | 21 | public void start(int c) { 22 | this.setCount(c); 23 | exec = Executors.newScheduledThreadPool(1); 24 | exec.scheduleAtFixedRate(new Task(),1,1, TimeUnit.MINUTES); 25 | } 26 | 27 | private class Task implements Runnable{ 28 | @Override 29 | public void run() { 30 | count--; 31 | if (count <= 0) { 32 | count = 0; 33 | exec.shutdownNow(); 34 | } 35 | } 36 | } 37 | 38 | public void setCount(int c) { 39 | count = c; 40 | } 41 | 42 | public int getCount() { 43 | return count; 44 | } 45 | 46 | /** 47 | * 是否倒数结束 48 | * @return 49 | */ 50 | public boolean bEnd() { 51 | if (count == 0) { 52 | return true; 53 | } 54 | return false; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/util/MathUtil.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.util; 2 | 3 | import java.math.BigDecimal; 4 | import java.math.RoundingMode; 5 | import java.util.Random; 6 | 7 | /** 8 | * 处理数字工具类 9 | * @author yuanfeng.z 10 | * @date 2020/7/31 1:07 11 | */ 12 | public class MathUtil { 13 | /** 14 | * 移动小数位 15 | * @param data 目标数据 16 | * @param digits 移动位数 17 | * @return 18 | */ 19 | public static BigDecimal moveDigits(BigDecimal data, Integer digits) { 20 | for (int i = 0; i < digits; i++) { 21 | data = data.multiply(new BigDecimal("0.1")); 22 | } 23 | return data; 24 | } 25 | 26 | /** 27 | * 调整数据最小单位 28 | * @param data 29 | * @param minUtil 30 | * @return 31 | */ 32 | public static BigDecimal adjustMinUtil(BigDecimal data, BigDecimal minUtil, final RoundingMode roundingMode) { 33 | BigDecimal[] arg = BigDecimalUtil.divideAndRemainder(data, minUtil); 34 | 35 | final BigDecimal res = data.subtract(arg[1]); 36 | // bid、ask区别处理 37 | if (roundingMode == RoundingMode.UP) { 38 | return res.add(minUtil); 39 | } else { 40 | return res; 41 | } 42 | } 43 | 44 | public static Integer randomInt(int seed) { 45 | Random random = new Random(); 46 | Integer res = random.nextInt(seed); 47 | return res; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /framework/src/main/java/com/zyf/framework/scheduling/ScheduleTaskManager.java: -------------------------------------------------------------------------------- 1 | package com.zyf.framework.scheduling; 2 | 3 | import lombok.Getter; 4 | import org.quartz.SchedulerException; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.concurrent.ScheduledExecutorService; 9 | 10 | /** 11 | * 定时任务管理类 12 | * 13 | * @author yuanfeng.z 14 | * @date 2020/7/24 23:36 15 | */ 16 | @Getter 17 | public class ScheduleTaskManager { 18 | 19 | /** 20 | * 策略任务列表 21 | */ 22 | private List scheduledTasks = new ArrayList<>(16); 23 | 24 | private static ScheduleTaskManager scheduleTaskManager = new ScheduleTaskManager(); 25 | 26 | public static ScheduleTaskManager getInstance() { 27 | return scheduleTaskManager; 28 | } 29 | 30 | /** 31 | * 添加任务 32 | * 33 | * @param scheduledTask 定时任务 34 | */ 35 | public void add(ScheduledTask scheduledTask) { 36 | this.scheduledTasks.add(scheduledTask); 37 | } 38 | 39 | /** 40 | * 启动任务 41 | */ 42 | public void start() { 43 | for (ScheduledTask scheduledTask : this.scheduledTasks) { 44 | scheduledTask.start(); 45 | } 46 | } 47 | 48 | public void shutdown() throws SchedulerException { 49 | for (ScheduledTask scheduledTask : this.scheduledTasks) { 50 | scheduledTask.shutdown(); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/enums/Side.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model.enums; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | 5 | /** 6 | * 买卖方向 7 | * 8 | * @author yuanfeng.z 9 | * @date 2019/6/29 10:30 10 | */ 11 | public enum Side { 12 | 13 | /** 14 | * 买 15 | */ 16 | BUY("buy"), 17 | 18 | /** 19 | * 卖 20 | */ 21 | SELL("sell"), 22 | 23 | /****期货*****/ 24 | 25 | OPEN_LONG("openLong"), 26 | 27 | OPEN_SHORT("openShort"), 28 | 29 | CLOSE_LONG("closeLong"), 30 | 31 | CLOSE_SHORT("closeShort"); 32 | 33 | 34 | private String value; 35 | 36 | Side(String value) { 37 | this.value = value; 38 | } 39 | 40 | public String getValue() { 41 | return value; 42 | } 43 | 44 | public static Side getByValue(String side) { 45 | if (StrUtil.isBlank(side)) { 46 | return null; 47 | }else if (BUY.value.equals(side)) { 48 | return BUY; 49 | } else if (SELL.value.equals(side)) { 50 | return SELL; 51 | }else if (OPEN_LONG.value.equals(side)) { 52 | return OPEN_LONG; 53 | }else if (OPEN_SHORT.value.equals(side)) { 54 | return OPEN_SHORT; 55 | }else if (CLOSE_LONG.value.equals(side)) { 56 | return CLOSE_LONG; 57 | }else if (CLOSE_SHORT.value.equals(side)) { 58 | return CLOSE_SHORT; 59 | } 60 | return null; 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/Depth.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model; 2 | 3 | import lombok.*; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * 市场深度类 (添加@Setter和@NoArgsConstructor(force = true)注解, 9 | * 目的是解决Jackson2JsonMessageConverter序列化、反序列化问题) 10 | * 11 | * @author yuanfeng.z 12 | * @date 2019/6/24 19:58 13 | */ 14 | @Setter 15 | @Getter 16 | @ToString 17 | @EqualsAndHashCode(callSuper = false) 18 | @NoArgsConstructor 19 | public class Depth extends BaseData { 20 | /** 21 | * 原始数据,以防定义字段不够用 22 | */ 23 | private String originData; 24 | 25 | /** 26 | * 时间戳 27 | */ 28 | private Long timestamp; 29 | 30 | /** 31 | * 买盘深度 32 | */ 33 | private List bids; 34 | 35 | /** 36 | * 卖盘深度Level 37 | */ 38 | private List asks; 39 | 40 | public Depth(String originData, Long timestamp, List bids, List asks) { 41 | this.originData = originData; 42 | this.timestamp = timestamp; 43 | this.bids = bids; 44 | this.asks = asks; 45 | } 46 | 47 | public Depth(String exchangeName, String instrumentId, String originData, Long timestamp, 48 | List bids, List asks) { 49 | this.exchangeName = exchangeName; 50 | this.instrumentId = instrumentId; 51 | this.originData = originData; 52 | this.timestamp = timestamp; 53 | this.bids = bids; 54 | this.asks = asks; 55 | } 56 | } 57 | 58 | -------------------------------------------------------------------------------- /trade/src/test/java/com/zyf/trade/HuobiProTest.java: -------------------------------------------------------------------------------- 1 | package com.zyf.trade; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.alibaba.fastjson.JSONObject; 5 | import com.zyf.common.model.Order; 6 | import com.zyf.common.model.Trade; 7 | import com.zyf.trade.http.option.HuobiProTradeOptionExchange; 8 | import lombok.extern.slf4j.Slf4j; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | @Slf4j 14 | public class HuobiProTest { 15 | public static void main(String[] args) { 16 | HuobiProTradeOptionExchange huobiProTradeOptionExchange = 17 | new HuobiProTradeOptionExchange("xxx-xxx-xxx-xx", 18 | "xx-xx-xx-xx"); 19 | List lists = huobiProTradeOptionExchange.getOrders("BTC"); 20 | List trades = new ArrayList<>(); 21 | for (Order order : lists) { 22 | JSONObject json = JSON.parseObject(order.getOriginData()); 23 | Long time = order.getTimestamp(); 24 | String orderType = json.getString("order_type"); 25 | StringBuilder sb = new StringBuilder(); 26 | sb.append(order.getOrderId()) 27 | .append("/") 28 | .append(time) 29 | .append("/") 30 | .append(orderType); 31 | trades.addAll(huobiProTradeOptionExchange.getTrades("BTC", sb.toString())); 32 | log.info(trades.toString()); 33 | } 34 | log.info("" +trades.size()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/Ticker.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model; 2 | 3 | 4 | import lombok.Getter; 5 | import lombok.ToString; 6 | 7 | import java.io.Serializable; 8 | import java.math.BigDecimal; 9 | 10 | /** 11 | /** 12 | * 市场心跳类 13 | * @author yuanfeng.z 14 | * @date 2019/6/24 18:09 15 | */ 16 | @Getter 17 | @ToString 18 | public class Ticker implements Serializable { 19 | private static final long serialVersionUID = -6958478794810546513L; 20 | 21 | /** 22 | * 原始数据,以防定义字段不够用 23 | */ 24 | private final String originData; 25 | 26 | /** 27 | * 时间戳 28 | */ 29 | private final Long timestamp; 30 | 31 | /** 32 | * 开盘价 33 | */ 34 | private final BigDecimal open; 35 | 36 | /** 37 | * 收盘价 38 | */ 39 | private final BigDecimal close; 40 | 41 | /** 42 | * 最低价 43 | */ 44 | private final BigDecimal low; 45 | 46 | /** 47 | * 最高价 48 | */ 49 | private final BigDecimal high; 50 | 51 | /** 52 | * 24小时量 53 | */ 54 | private final BigDecimal vol; 55 | 56 | public Ticker(String originData, Long timestamp, BigDecimal open, BigDecimal high, 57 | BigDecimal low, BigDecimal close, BigDecimal vol) { 58 | this.originData = originData; 59 | this.timestamp = timestamp; 60 | this.open = open; 61 | this.high = high; 62 | this.low = low; 63 | this.close = close; 64 | this.vol = vol; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/enums/DealType.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model.enums; 2 | 3 | import cn.hutool.core.util.StrUtil; 4 | 5 | /** 6 | * 合约类型 7 | * 8 | * @author yuanfeng.z 9 | * @date 2019-12-23 10 | */ 11 | public enum DealType { 12 | 13 | /** 14 | * 开仓 15 | */ 16 | OPEN_POSITION("OPEN_POSITION"), 17 | 18 | /** 19 | * 平仓 20 | */ 21 | CLOSE_POSITION("CLOSE_POSITION"), 22 | 23 | /** 24 | * 爆仓 25 | */ 26 | BREAK_POSITION("BREAK_POSITION"), 27 | 28 | /** 29 | * 加仓 30 | */ 31 | ADD_POSITION("ADD_POSITION"), 32 | 33 | /** 34 | * 减仓 35 | */ 36 | SUB_POSITION("SUB_POSITION"); 37 | 38 | private String value; 39 | 40 | DealType(String value) { 41 | this.value = value; 42 | } 43 | 44 | public String getValue() { 45 | return value; 46 | } 47 | 48 | public static DealType getByValue(String type) { 49 | if (StrUtil.isBlank(type)) { 50 | return null; 51 | } 52 | else if(OPEN_POSITION.value.equals(type)){ 53 | return OPEN_POSITION; 54 | } 55 | else if(CLOSE_POSITION.value.equals(type)){ 56 | return CLOSE_POSITION; 57 | } 58 | else if(BREAK_POSITION.value.equals(type)){ 59 | return BREAK_POSITION; 60 | } 61 | else if(SUB_POSITION.value.equals(type)){ 62 | return SUB_POSITION; 63 | } 64 | return null; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /common/target/classes/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootLogger=info,error,CONSOLE 2 | 3 | log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender 4 | log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout 5 | log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n 6 | 7 | log4j.logger.info=info 8 | log4j.appender.info=org.apache.log4j.DailyRollingFileAppender 9 | log4j.appender.info.layout=org.apache.log4j.PatternLayout 10 | log4j.appender.info.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n 11 | log4j.appender.info.datePattern='.'yyyy-MM-dd 12 | log4j.appender.info.Threshold = info 13 | log4j.appender.info.append=true 14 | log4j.appender.info.File=logs/info.log 15 | 16 | log4j.logger.error=error 17 | log4j.appender.error=org.apache.log4j.DailyRollingFileAppender 18 | log4j.appender.error.layout=org.apache.log4j.PatternLayout 19 | log4j.appender.error.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n 20 | log4j.appender.error.datePattern='.'yyyy-MM-dd 21 | log4j.appender.error.Threshold = error 22 | log4j.appender.error.append=true 23 | log4j.appender.error.File=logs/error.log 24 | 25 | #log4j.logger.DEBUG=debug 26 | #log4j.appender.DEBUG=org.apache.log4j.DailyRollingFileAppender 27 | #log4j.appender.DEBUG.layout=org.apache.log4j.PatternLayout 28 | #log4j.appender.DEBUG.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n 29 | #log4j.appender.DEBUG.datePattern='.'yyyy-MM-dd 30 | #log4j.appender.DEBUG.Threshold = debug 31 | #log4j.appender.DEBUG.append=true 32 | #log4j.appender.DEBUG.File=logs/debug.log -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 36 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/Kline.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.ToString; 6 | 7 | import java.io.Serializable; 8 | import java.math.BigDecimal; 9 | 10 | /** 11 | * k线类 12 | * @author yuanfeng.z 13 | * @date 2019/6/29 11:34 14 | */ 15 | @Getter 16 | @ToString 17 | @EqualsAndHashCode 18 | public class Kline implements Serializable { 19 | private static final long serialVersionUID = 8454688387229030586L; 20 | 21 | /** 22 | * 原始数据,以防定义字段不够用 23 | */ 24 | private final String originData; 25 | 26 | /** 27 | * 时间戳 28 | */ 29 | private final Long timestamp; 30 | 31 | /** 32 | * 开盘价 33 | */ 34 | private final BigDecimal open; 35 | 36 | /** 37 | * 收盘价 38 | */ 39 | private final BigDecimal close; 40 | 41 | /** 42 | * 最低价 43 | */ 44 | private final BigDecimal low; 45 | 46 | /** 47 | * 最高价 48 | */ 49 | private final BigDecimal high; 50 | 51 | /** 52 | * 交易量 53 | */ 54 | private final BigDecimal volume; 55 | 56 | public Kline(String originData, Long timestamp, BigDecimal open, BigDecimal high, 57 | BigDecimal low, BigDecimal close, BigDecimal volume) { 58 | this.originData = originData; 59 | this.timestamp = timestamp; 60 | this.open = open; 61 | this.high = high; 62 | this.low = low; 63 | this.close = close; 64 | this.volume = volume; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/Trade.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.ToString; 6 | 7 | import java.io.Serializable; 8 | import java.math.BigDecimal; 9 | 10 | /** 11 | * 成交明细类 12 | * @author yuanfeng.z 13 | * @date 2019/6/29 11:26 14 | */ 15 | @Getter 16 | @ToString 17 | @EqualsAndHashCode 18 | public class Trade implements Serializable { 19 | private static final long serialVersionUID = -211250079118365083L; 20 | 21 | /** 22 | * 原始数据,以防定义字段不够用 23 | */ 24 | private final String originData; 25 | 26 | /** 27 | * 时间戳 28 | */ 29 | private final Long timestamp; 30 | 31 | /** 32 | * 订单id 33 | */ 34 | private final String orderId; 35 | 36 | /** 37 | * 成交id 38 | */ 39 | private final String dealId; 40 | 41 | /** 42 | * 价格 43 | */ 44 | private final BigDecimal price; 45 | 46 | /** 47 | * 数量 48 | */ 49 | private final BigDecimal quantity; 50 | 51 | /** 52 | * 手续费 53 | */ 54 | private final BigDecimal fee; 55 | 56 | /** 57 | * 手续费货币 58 | */ 59 | private final String feeCurrency; 60 | 61 | public Trade(String originData, Long timestamp, String orderId, String dealId, 62 | BigDecimal price, BigDecimal quantity, BigDecimal fee, String feeCurrency) { 63 | this.originData = originData; 64 | this.timestamp = timestamp; 65 | this.orderId = orderId; 66 | this.dealId = dealId; 67 | this.price = price; 68 | this.quantity = quantity; 69 | this.fee = fee; 70 | this.feeCurrency = feeCurrency; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/Position.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model; 2 | 3 | import com.zyf.common.model.enums.Side; 4 | import com.zyf.common.model.enums.State; 5 | import com.zyf.common.model.enums.Type; 6 | import lombok.Data; 7 | import lombok.EqualsAndHashCode; 8 | import lombok.Getter; 9 | import lombok.ToString; 10 | 11 | import java.io.Serializable; 12 | import java.math.BigDecimal; 13 | 14 | /** 15 | * 持仓类 16 | * @author yuanfeng.z 17 | * @date 2019/6/29 10:14 18 | */ 19 | @Getter 20 | @ToString 21 | @Data 22 | @EqualsAndHashCode 23 | public class Position implements Serializable { 24 | private static final long serialVersionUID = -5321844919458631192L; 25 | 26 | /** 27 | * 原始数据,以防定义字段不够用 28 | */ 29 | private final String originData; 30 | 31 | /** 32 | * 时间戳 33 | */ 34 | private final Long timestamp; 35 | 36 | /** 37 | * 合约名 38 | */ 39 | private final String instrument; 40 | 41 | /** 42 | * 预估强平价 43 | */ 44 | private final BigDecimal liquidationPrice; 45 | 46 | /** 47 | * 持仓数量 48 | */ 49 | private final BigDecimal quantity; 50 | 51 | /** 52 | * 可平数量 53 | */ 54 | private final BigDecimal availQuantity; 55 | 56 | /** 57 | * 开仓平均价 58 | */ 59 | private final BigDecimal avgCost; 60 | 61 | /** 62 | * 结算基准价 63 | */ 64 | private final BigDecimal settlementPrice; 65 | 66 | /** 67 | * 已结算收益 68 | */ 69 | private final BigDecimal settledPnl; 70 | 71 | /** 72 | * 未实现盈亏 73 | */ 74 | private final BigDecimal unrealizedPnl; 75 | 76 | /** 77 | * 最新成交价 78 | */ 79 | private final BigDecimal last; 80 | 81 | /** 82 | * 保证金 83 | */ 84 | private final BigDecimal margin; 85 | 86 | /** 87 | * 方向 88 | */ 89 | private final Side side; 90 | } 91 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/future/InstrumentFut.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model.future; 2 | 3 | import lombok.*; 4 | 5 | import java.math.BigDecimal; 6 | 7 | /** 8 | * 期货合约类 9 | * 10 | * @author yuanfeng.z 11 | * @date 2020/7/27 15:29 12 | */ 13 | @Getter 14 | @ToString 15 | @EqualsAndHashCode 16 | @NoArgsConstructor 17 | public class InstrumentFut { 18 | 19 | /** 20 | * 原始数据,以防定义字段不够用 21 | */ 22 | private String originData; 23 | 24 | /** 25 | * 名称 26 | */ 27 | private String name; 28 | 29 | /** 30 | * 币 31 | */ 32 | private String baseCurrency; 33 | 34 | /** 35 | * 计价 36 | */ 37 | private String countCurrency; 38 | 39 | /** 40 | * 最小单位 41 | */ 42 | private BigDecimal minTradeSize; 43 | 44 | /** 45 | * 精度,估计是计价精度 46 | */ 47 | private Integer countPrecision; 48 | 49 | /** 50 | * 合约类型: (this_week:当周 next_week:下周 quarter:当季 next_quarter:次季) 51 | */ 52 | private String contractType; 53 | 54 | /** 55 | * 创建时间 56 | */ 57 | private Long created; 58 | 59 | /** 60 | * 到期时间 61 | */ 62 | private Long expired; 63 | 64 | public InstrumentFut(String originData, String name, String baseCurrency, String countCurrency, 65 | BigDecimal minTradeSize, Integer countPrecision, 66 | String contractType, Long created, Long expired) { 67 | this.originData = originData; 68 | this.name = name; 69 | this.baseCurrency = baseCurrency; 70 | this.baseCurrency = baseCurrency; 71 | this.countCurrency = countCurrency; 72 | this.minTradeSize = minTradeSize; 73 | this.countPrecision = countPrecision; 74 | this.contractType = contractType; 75 | this.created = created; 76 | this.expired = expired; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /baseservice/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | easy-quant 7 | com.zyf 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | baseservice 13 | 14 | 15 | 16 | com.alibaba 17 | fastjson 18 | 1.2.58 19 | compile 20 | 21 | 22 | commons-codec 23 | commons-codec 24 | 1.14 25 | 26 | 27 | com.zyf 28 | common 29 | 1.0-SNAPSHOT 30 | compile 31 | 32 | 33 | junit 34 | junit 35 | 4.12 36 | test 37 | 38 | 39 | commons-io 40 | commons-io 41 | 2.2 42 | 43 | 44 | commons-httpclient 45 | commons-httpclient 46 | 3.1 47 | compile 48 | 49 | 50 | -------------------------------------------------------------------------------- /framework/src/main/java/com/zyf/framework/boot/Environment.java: -------------------------------------------------------------------------------- 1 | package com.zyf.framework.boot; 2 | 3 | import cn.hutool.core.io.resource.ClassPathResource; 4 | import com.alibaba.fastjson.JSON; 5 | import com.alibaba.fastjson.JSONException; 6 | import com.alibaba.fastjson.JSONObject; 7 | import com.zyf.framework.util.FileUtil; 8 | import lombok.extern.slf4j.Slf4j; 9 | 10 | import java.io.*; 11 | import java.util.Objects; 12 | 13 | /** 14 | * 环境配置类 15 | * @author yuanfeng.z 16 | * @date 2020/7/22 17:20 17 | */ 18 | @Slf4j 19 | public class Environment { 20 | 21 | /** 22 | * 策略配置文件名前缀 23 | */ 24 | private final static String CONFIG_PROPERTY = "--config-name:"; 25 | 26 | /** 27 | * 策略配置默认 28 | */ 29 | private final static String DEFAULT_CONFIG_NAME = "config.json"; 30 | 31 | /** 32 | * 加载配置文件 33 | * @param args 程序入参 34 | * @return 35 | */ 36 | public static JSONObject prepareConfig(String[] args) { 37 | String name = DEFAULT_CONFIG_NAME; 38 | 39 | // 若指定文件,则加载指定路径文件,否则使用默认路径 40 | for (String arg : args) { 41 | if (arg.startsWith(CONFIG_PROPERTY)) { 42 | name = arg.split(":")[1]; 43 | log.info("config name is : {}", name); 44 | break; 45 | } 46 | } 47 | 48 | log.info("load default config"); 49 | 50 | // 加载配置文件 51 | String property = FileUtil.readJsonFile(name); 52 | log.info(String.format("load file %s success.", name)); 53 | 54 | JSONObject json; 55 | try { 56 | json = JSON.parseObject(property); 57 | } catch (JSONException e) { 58 | throw new JSONException("The config file JSON format is not correct"); 59 | } 60 | if (Objects.isNull(json)) { 61 | throw new RuntimeException("The config file content is empty"); 62 | } 63 | 64 | return json; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /framework/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | easy-quant 7 | com.zyf 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | framework 13 | 14 | 15 | 16 | 17 | com.zyf 18 | trade 19 | 1.0-SNAPSHOT 20 | compile 21 | 22 | 23 | 24 | com.zyf 25 | marketdata 26 | 1.0-SNAPSHOT 27 | compile 28 | 29 | 30 | 31 | org.quartz-scheduler 32 | quartz 33 | 2.3.2 34 | 35 | 36 | 37 | 38 | com.sun.mail 39 | javax.mail 40 | 1.6.2 41 | 42 | 43 | org.thymeleaf 44 | thymeleaf-spring5 45 | 3.0.9.RELEASE 46 | compile 47 | 48 | 49 | org.thymeleaf.extras 50 | thymeleaf-extras-java8time 51 | 3.0.1.RELEASE 52 | compile 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /strategy/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | easy-quant 7 | com.zyf 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | strategy 13 | 14 | 15 | 1.0 16 | 17 | 18 | 19 | 20 | com.zyf 21 | framework 22 | 1.0-SNAPSHOT 23 | compile 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | maven-assembly-plugin 32 | 33 | 34 | 35 | 36 | com.zyf.strategy.Main 37 | 38 | 39 | 40 | jar-with-dependencies 41 | 42 | 43 | 44 | 45 | make-assembly 46 | package 47 | 48 | single 49 | 50 | 51 | 52 | 53 | 54 | 55 | DpoStrategyReverse-${jar.version} 56 | 57 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/InstrumentTrade.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model; 2 | 3 | import com.zyf.common.model.enums.DealType; 4 | import com.zyf.common.model.enums.Role; 5 | import com.zyf.common.model.enums.Side; 6 | import com.zyf.common.model.enums.Type; 7 | import lombok.Getter; 8 | import lombok.Setter; 9 | 10 | import java.math.BigDecimal; 11 | import java.util.Date; 12 | 13 | /** 14 | * 合约成交明细 15 | * @author yuanfeng.z 16 | * @date 2019/12/23 17 | */ 18 | @Getter 19 | @Setter 20 | public class InstrumentTrade { 21 | 22 | /** 23 | * 原始数据,以防定义字段不够用 24 | */ 25 | private String originData; 26 | 27 | /** 28 | * id 29 | */ 30 | private Long id; 31 | 32 | /** 33 | * coin_symbol 34 | */ 35 | private String coinSymbol; 36 | 37 | /** 38 | * 合约符号 39 | */ 40 | private String pair; 41 | 42 | /** 43 | * 类型,1开仓, 2平仓, 3爆仓, 4减仓 44 | */ 45 | private DealType dealType; 46 | 47 | /** 48 | * side 1开多,2开空 49 | */ 50 | private Integer orderSide; 51 | 52 | /** 53 | * price_open 委托价格 54 | */ 55 | private BigDecimal priceOpen; 56 | 57 | /** 58 | * price 开仓均价 59 | */ 60 | private BigDecimal price; 61 | 62 | /** 63 | * price_deal 成交价格 64 | */ 65 | private BigDecimal priceDeal; 66 | 67 | /** 68 | * 合约张数 69 | */ 70 | private BigDecimal contract; 71 | 72 | /** 73 | * 盈亏 74 | */ 75 | private BigDecimal profit; 76 | 77 | /** 78 | * 手续费 79 | */ 80 | private BigDecimal fee; 81 | 82 | /** 83 | * 时间 84 | */ 85 | private Date date; 86 | 87 | /** 88 | * 费率 89 | */ 90 | private BigDecimal feeRate; 91 | 92 | /** 93 | * 角色 94 | */ 95 | private Role role; 96 | 97 | /** 98 | * buy or sell 99 | */ 100 | private Side side; 101 | 102 | /** 103 | * "limit,"market"或"liquidation" 104 | */ 105 | private Type type; 106 | 107 | } 108 | -------------------------------------------------------------------------------- /framework/src/main/java/com/zyf/framework/util/FileUtil.java: -------------------------------------------------------------------------------- 1 | package com.zyf.framework.util; 2 | 3 | import java.io.*; 4 | import java.net.URLDecoder; 5 | 6 | /** 7 | * 文件工具 8 | * 9 | * @author yuanfeng.z 10 | * @date 2020/8/7 1:58 11 | */ 12 | public class FileUtil { 13 | 14 | /** 15 | * 读取json文件 16 | * 17 | * @param fileName 文件名 18 | * @return 19 | */ 20 | public static String readJsonFile(String fileName) { 21 | String jsonStr = ""; 22 | try { 23 | InputStream stream = FileUtil.class.getClassLoader().getResourceAsStream(fileName); 24 | Reader reader = new InputStreamReader(stream, "utf-8"); 25 | int ch = 0; 26 | StringBuffer sb = new StringBuffer(); 27 | while ((ch = reader.read()) != -1) { 28 | sb.append((char) ch); 29 | } 30 | reader.close(); 31 | jsonStr = sb.toString(); 32 | return jsonStr; 33 | } catch (IOException e) { 34 | e.printStackTrace(); 35 | String message = String.format("load file %s failed.", fileName); 36 | throw new RuntimeException(message); 37 | } 38 | } 39 | 40 | /** 41 | * 写json文件 42 | * 43 | * @param fileName 文件名 44 | * @param content json格式字符串 45 | */ 46 | public static void writeJsonFile(String fileName, String content) { 47 | try { 48 | boolean isWin = System.getProperty("os.name").toLowerCase().contains("win"); 49 | FileWriter fileWriter = null; 50 | if (isWin) { 51 | java.net.URL uri = FileUtil.class.getClass().getResource("/"); 52 | fileWriter = new FileWriter(uri.getPath() + "/" + fileName); 53 | } else { 54 | fileWriter = new FileWriter("./" + fileName); 55 | } 56 | fileWriter.write(content); 57 | fileWriter.flush(); 58 | fileWriter.close(); 59 | } catch (IOException e) { 60 | e.printStackTrace(); 61 | String message = String.format("load file %s failed.", fileName); 62 | throw new RuntimeException(message); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /marketdata/src/main/java/com/zyf/marketdata/factory/MdExchangeFactory.java: -------------------------------------------------------------------------------- 1 | package com.zyf.marketdata.factory; 2 | 3 | import com.zyf.baseservice.IMdExchange; 4 | import com.zyf.common.model.enums.ExchangeEnum; 5 | import com.zyf.common.model.enums.SecuritiesTypeEnum; 6 | import com.zyf.common.util.CommomUtil; 7 | import com.zyf.marketdata.http.future.HuobiProMdFutExchange; 8 | import com.zyf.marketdata.http.future.OkexMdFutExchange; 9 | import com.zyf.marketdata.http.option.DeribitMdExchange; 10 | import com.zyf.marketdata.http.stock.HuobiProMdExchange; 11 | import com.zyf.marketdata.http.stock.OkexMdExchange; 12 | 13 | /** 14 | * 行情数据交易所工厂类 15 | * 16 | * @author yuanfeng.z 17 | * @date 2019/6/25 15:14 18 | */ 19 | public class MdExchangeFactory { 20 | 21 | /** 22 | * 生产工厂方法 23 | * @param exchangeName 交易所名字 24 | * @return 25 | */ 26 | public static IMdExchange createMdExchange(ExchangeEnum exchangeName, SecuritiesTypeEnum type) { 27 | if (SecuritiesTypeEnum.STOCK.equals(type)) { 28 | if (exchangeName.equals(ExchangeEnum.OKEXV3)) { 29 | return OkexMdExchange.getInstance(); 30 | } else if (exchangeName.equals(ExchangeEnum.HUOBIPRO)) { 31 | return HuobiProMdExchange.getInstance(); 32 | } else if (exchangeName.equals(ExchangeEnum.DERIBIT)) { 33 | return DeribitMdExchange.getInstance(); 34 | } 35 | } 36 | 37 | if (SecuritiesTypeEnum.FUTURE.equals(type)) { 38 | if (exchangeName.equals(ExchangeEnum.HUOBIPRO)) { 39 | return HuobiProMdFutExchange.getInstance(); 40 | } else if (exchangeName.equals(ExchangeEnum.OKEXV3)) { 41 | return OkexMdFutExchange.getInstance(); 42 | } 43 | } 44 | return null; 45 | } 46 | 47 | /** 48 | * 创建行情交易所实例 49 | * 50 | * @param exchangeName 交易所名字 51 | * @param type 证券类型 52 | * @return 53 | */ 54 | public static IMdExchange createMdExchange(String exchangeName, String type) { 55 | ExchangeEnum exchangeType = CommomUtil.toExchangeEnum(exchangeName); 56 | SecuritiesTypeEnum securitiesType = CommomUtil.toSecuritiesTypeEnum(type); 57 | return MdExchangeFactory.createMdExchange(exchangeType, securitiesType); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /marketdata/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | easy-quant 7 | com.zyf 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | marketdata 13 | 14 | 15 | 1.0.0 16 | 17 | 18 | 19 | 20 | com.zyf 21 | baseservice 22 | 1.0-SNAPSHOT 23 | compile 24 | 25 | 26 | junit 27 | junit 28 | 4.12 29 | compile 30 | 31 | 32 | 33 | com.google.code.gson 34 | gson 35 | 2.8.5 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | maven-assembly-plugin 44 | 45 | 46 | jar-with-dependencies 47 | 48 | 49 | 50 | 51 | make-assembly 52 | package 53 | 54 | single 55 | 56 | 57 | 58 | 59 | 60 | 61 | marketdata-${jar.version} 62 | 63 | 64 | -------------------------------------------------------------------------------- /trade/src/main/java/com/zyf/trade/factory/TradeExchangeFactory.java: -------------------------------------------------------------------------------- 1 | package com.zyf.trade.factory; 2 | 3 | import com.zyf.baseservice.ITradeExchange; 4 | import com.zyf.common.model.enums.ExchangeEnum; 5 | import com.zyf.common.model.enums.SecuritiesTypeEnum; 6 | import com.zyf.common.util.CommomUtil; 7 | import com.zyf.trade.http.future.HuobiProTradeFutExchange; 8 | import com.zyf.trade.http.future.OkexTradeFutExchange; 9 | import com.zyf.trade.http.option.DeribitTradeExchange; 10 | import com.zyf.trade.http.stock.HuobiProTradeExchange; 11 | import com.zyf.trade.http.stock.OkexTradeExchange; 12 | 13 | /** 14 | * 行情数据交易所工厂类 15 | * @author yuanfeng.z 16 | * @date 2019/6/25 15:14 17 | */ 18 | public class TradeExchangeFactory { 19 | 20 | /** 21 | * 创建实例 22 | * @param exchangeName 交易所名字 23 | * @param type 证券类型 24 | * @param accessKey 公钥 25 | * @param secretKey 密钥 26 | * @return 27 | */ 28 | public static ITradeExchange createTradeExchange(ExchangeEnum exchangeName, SecuritiesTypeEnum type, String accessKey, String secretKey) { 29 | if (SecuritiesTypeEnum.STOCK.equals(type)) { 30 | if (exchangeName.equals(ExchangeEnum.OKEXV3)) { 31 | return new OkexTradeExchange(accessKey, secretKey); 32 | } else if (exchangeName.equals(ExchangeEnum.HUOBIPRO)) { 33 | return new HuobiProTradeExchange(accessKey, secretKey); 34 | } else if (exchangeName.equals(ExchangeEnum.DERIBIT)) { 35 | return new DeribitTradeExchange(accessKey, secretKey); 36 | } 37 | } 38 | 39 | if (SecuritiesTypeEnum.FUTURE.equals(type)) { 40 | if (exchangeName.equals(ExchangeEnum.HUOBIPRO)) { 41 | return new HuobiProTradeFutExchange(accessKey, secretKey); 42 | } else if (exchangeName.equals(ExchangeEnum.OKEXV3)) { 43 | return new OkexTradeFutExchange(accessKey, secretKey); 44 | } 45 | } 46 | 47 | return null; 48 | } 49 | 50 | /** 51 | * 创建交易交易所类 52 | * @param exchangeName 交易所名字 53 | * @param type 证券类型 54 | * @param accessKey 公钥 55 | * @param secretKey 密钥 56 | * @return 57 | */ 58 | public static ITradeExchange createTradeExchange(String exchangeName, String type, String accessKey, String secretKey) { 59 | ExchangeEnum exchangeType = CommomUtil.toExchangeEnum(exchangeName); 60 | SecuritiesTypeEnum securitiesType = CommomUtil.toSecuritiesTypeEnum(type); 61 | return TradeExchangeFactory.createTradeExchange(exchangeType, securitiesType, accessKey, secretKey); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /framework/src/main/java/com/zyf/framework/boot/BaseStrategy.java: -------------------------------------------------------------------------------- 1 | package com.zyf.framework.boot; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.zyf.baseservice.IExchange; 5 | import com.zyf.baseservice.IMdExchange; 6 | import com.zyf.baseservice.ITradeExchange; 7 | import com.zyf.common.model.Depth; 8 | import com.zyf.marketdata.factory.MdExchangeFactory; 9 | import com.zyf.marketdata.proxy.MdExchangeProxy; 10 | import com.zyf.trade.factory.TradeExchangeFactory; 11 | import com.zyf.trade.proxy.TradeExchangeProxy; 12 | 13 | import java.math.BigDecimal; 14 | import java.util.logging.Logger; 15 | 16 | /** 17 | * 策略基类 18 | * 19 | * @author yuanfeng.z 20 | * @date 2020/7/22 19:01 21 | */ 22 | public abstract class BaseStrategy { 23 | /** 24 | * 日志 25 | */ 26 | protected Logger log; 27 | 28 | /** 29 | * 交易所名字 30 | */ 31 | protected String exchangeName; 32 | 33 | /** 34 | * 本实例id(配置名称) 35 | */ 36 | protected String id; 37 | 38 | /** 39 | * 币对 40 | */ 41 | protected String symbol; 42 | 43 | /** 44 | * 本实例配置 45 | */ 46 | protected JSONObject config; 47 | 48 | /** 49 | * 公有交易所类 50 | */ 51 | protected IMdExchange mdE; 52 | 53 | /** 54 | * 私有交易所类 55 | */ 56 | protected ITradeExchange tradeE; 57 | 58 | /** 59 | * 初始策略运行中数据文件路径 60 | */ 61 | protected String storeFile; 62 | 63 | /** 64 | * 0:初始化策略 1:恢复策略 65 | */ 66 | protected Integer bInit = 0; 67 | 68 | /** 69 | * 初始化方法 70 | */ 71 | protected abstract void init(); 72 | 73 | /** 74 | * 恢复策略 75 | */ 76 | protected abstract void recovery(); 77 | 78 | /** 79 | * 默认循环 80 | */ 81 | protected void run() { 82 | } 83 | 84 | /** 85 | * 退出方法 86 | */ 87 | public void destroy() { 88 | } 89 | 90 | /** 91 | * 获取买一 92 | * @return 93 | */ 94 | public BigDecimal getBid1() { 95 | Depth depth = mdE.getDepth(symbol); 96 | BigDecimal bid1 = depth.getBids().get(0).getPrice(); 97 | return bid1; 98 | } 99 | 100 | /** 101 | * 获取卖一 102 | * @return 103 | */ 104 | public BigDecimal getAsk1() { 105 | Depth depth = mdE.getDepth(symbol); 106 | BigDecimal ask1 = depth.getAsks().get(0).getPrice(); 107 | return ask1; 108 | } 109 | 110 | @Override 111 | public String toString() { 112 | return "id: " + id + 113 | " symbol: " + symbol + 114 | " exchangeName: " + exchangeName + 115 | " config: " + config.toJSONString() + 116 | " mdE: " + mdE.toString() + 117 | " tradeE: " + tradeE.toString(); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/option/Instrument.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model.option; 2 | 3 | import lombok.*; 4 | 5 | import java.math.BigDecimal; 6 | /** 7 | * 期权合约类 8 | * @author yuanfeng.z 9 | * @date 2020/7/27 15:29 10 | */ 11 | @Getter 12 | @ToString 13 | @EqualsAndHashCode 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | public class Instrument { 17 | 18 | public enum Type { 19 | //期货 20 | FUTURE, 21 | //期权 22 | OPTION 23 | } 24 | 25 | public enum Settle { 26 | DAY, 27 | MONTH, 28 | WEEK, 29 | NEXT_WEEK, 30 | QUARTER, 31 | PERPETUAL 32 | } 33 | 34 | public enum OptionType { 35 | PUT, 36 | CALL 37 | } 38 | 39 | /** 40 | * 原始数据,以防定义字段不够用 41 | */ 42 | private String originData; 43 | 44 | /** 45 | * 名称 46 | */ 47 | private String name; 48 | 49 | /** 50 | * 类型 51 | */ 52 | private Type type; 53 | 54 | /** 55 | * 币 56 | */ 57 | private String baseCurrency; 58 | 59 | /** 60 | * 计价 61 | */ 62 | private String countCurrency; 63 | 64 | /** 65 | * 最小单位 66 | */ 67 | private BigDecimal minTradeSize; 68 | 69 | /** 70 | * 精度,估计是计价精度 71 | */ 72 | private Integer countPrecision; 73 | 74 | private BigDecimal tickSize; 75 | 76 | /** 77 | * 状态 78 | */ 79 | private Boolean active; 80 | 81 | /** 82 | * 结算类型 83 | */ 84 | private Settle settle; 85 | 86 | /** 87 | * 创建时间 88 | */ 89 | private Long created; 90 | 91 | /** 92 | * 到期时间 93 | */ 94 | private Long expired; 95 | 96 | /** 97 | * 行权价 98 | */ 99 | private BigDecimal strike; 100 | 101 | /** 102 | * 隐含波动率 103 | */ 104 | private BigDecimal iv; 105 | 106 | public Instrument(String originData, String name, Type type, String baseCurrency, String countCurrency, 107 | BigDecimal minTradeSize, Integer countPrecision, BigDecimal tickSize, Boolean active, 108 | BigDecimal iv, Settle settle, BigDecimal strike, Long created, Long expired) { 109 | this.originData = originData; 110 | this.name = name; 111 | this.type = type; 112 | this.baseCurrency = baseCurrency; 113 | this.baseCurrency = baseCurrency; 114 | this.countCurrency = countCurrency; 115 | this.minTradeSize = minTradeSize; 116 | this.countPrecision = countPrecision; 117 | this.tickSize = tickSize; 118 | this.active = active; 119 | this.iv = iv; 120 | this.settle = settle; 121 | this.strike = strike; 122 | this.created = created; 123 | this.expired = expired; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/Order.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model; 2 | 3 | import com.zyf.common.model.enums.Side; 4 | import com.zyf.common.model.enums.State; 5 | import com.zyf.common.model.enums.Type; 6 | import lombok.Data; 7 | import lombok.EqualsAndHashCode; 8 | import lombok.Getter; 9 | import lombok.ToString; 10 | 11 | import java.io.Serializable; 12 | import java.math.BigDecimal; 13 | import java.util.Objects; 14 | 15 | /** 16 | * 订单类 17 | * 18 | * @author yuanfeng.z 19 | * @date 2019/6/29 10:14 20 | */ 21 | @Getter 22 | @ToString 23 | @Data 24 | @EqualsAndHashCode 25 | public class Order implements Serializable { 26 | private static final long serialVersionUID = -8129844919458631192L; 27 | 28 | /** 29 | * 原始数据,以防定义字段不够用 30 | */ 31 | private final String originData; 32 | 33 | /** 34 | * 时间戳 35 | */ 36 | private final Long timestamp; 37 | 38 | /** 39 | * 订单id 40 | */ 41 | private final String orderId; 42 | 43 | /** 44 | * 价格 45 | */ 46 | private final BigDecimal price; 47 | 48 | /** 49 | * 数量 50 | */ 51 | private final BigDecimal quantity; 52 | 53 | /** 54 | * 成交数量 55 | */ 56 | private final BigDecimal deal; 57 | 58 | /** 59 | * 买卖方向 60 | */ 61 | private final Side side; 62 | 63 | /** 64 | * 类型(限价、市价等) 65 | */ 66 | private final Type type; 67 | 68 | /** 69 | * 状态(全部成交、未成交等) 70 | */ 71 | private final State state; 72 | 73 | 74 | public Order(String originData, Long timestamp, String orderId, BigDecimal price, BigDecimal quantity, BigDecimal deal, Side side, Type type, State state) { 75 | this.originData = originData; 76 | this.timestamp = timestamp; 77 | this.orderId = orderId; 78 | this.price = price; 79 | this.quantity = quantity; 80 | this.deal = deal; 81 | this.side = side; 82 | this.type = type; 83 | this.state = state; 84 | } 85 | 86 | public Order(String orderId, BigDecimal price, BigDecimal quantity, Side side) { 87 | this.originData = null; 88 | this.timestamp = null; 89 | this.orderId = orderId; 90 | this.price = price; 91 | this.quantity = quantity; 92 | this.deal = null; 93 | this.side = side; 94 | this.type = null; 95 | this.state = null; 96 | } 97 | 98 | @Override 99 | public boolean equals(Object o) { 100 | if (this == o) { 101 | return true; 102 | } 103 | if (o == null || getClass() != o.getClass()) { 104 | return false; 105 | } 106 | Order order = (Order) o; 107 | return Objects.equals(orderId, order.orderId); 108 | } 109 | 110 | @Override 111 | public int hashCode() { 112 | return Objects.hash(originData, timestamp, orderId, price, quantity, deal, side, type, state); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/exceptions/EHAErrorCodeEnum.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.exceptions; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | 5 | /** 6 | * Exchange Http Api Error Code Enum 7 | * @author yuanfeng.z 8 | * @date 2019/6/25 10:27 9 | */ 10 | public enum EHAErrorCodeEnum implements ErrorCode { 11 | 12 | /** 未指明的异常 */ 13 | UNSPECIFIED("500", "网络异常,延迟"), 14 | NO_SERVICE("404", "网络异常, 服务器熔断"), 15 | 16 | /** 接口异常 */ 17 | API_GET_TICKER("12001","获取ticker异常"), 18 | API_GET_KLINE("12002","获取kline异常"), 19 | API_GET_DEPTH("12003","获取深度异常"), 20 | API_GET_PRECISIONS("12004","获取精度异常"), 21 | API_GET_ACCOUNT("12005","获取账户信息异常"), 22 | API_GET_ASSET("12006","获取合约账户信息异常"), 23 | API_BUY_MARKET("12007","市价买入异常"), 24 | API_BUY_LIMIT("12008","限价买入异常"), 25 | API_SELL_MARKET("12009","市价卖出异常"), 26 | API_SELL_LIMIT("12010","限价卖出异常"), 27 | API_CANCEL_ORDER("12011","根据订单id撤单异常"), 28 | API_CANCEL_ORDERS("12012","批量撤单异常"), 29 | API_GET_ORDERS("12013","获取所有的订单异常"), 30 | API_GET_PENDING_ORDERS("12014","获取所有的正在挂的订单异常"), 31 | API_GET_ORDER("12015","获取指定id的订单信息异常"), 32 | API_GET_TRADE("12016","获取成交明细异常"), 33 | API_GET_INSTRUMENT_TRADE("12017","获取合约成交明细异常"), 34 | API_GET_CONTRACT("12018","根据合约获取当前仓位持仓张数异常"), 35 | API_GET__UNSETTLED_ORDERS("12019","根据合约获取未成交订单异常"), 36 | API_CANCEL_ALL("12020","API 根据合约撤掉所有订单异常"), 37 | API_PLACE_ORDERS("12021","合约批量下单异常"), 38 | 39 | // 通用异常 40 | ACCOUNT_BALANCE("11001", "账户余额不足"), 41 | QUANTITY_LOW("11002","下单量过低"); 42 | 43 | /** 错误码 */ 44 | private final String code; 45 | 46 | /** 描述 */ 47 | private final String description; 48 | 49 | /** 50 | * @param code 错误码 51 | * @param description 描述 52 | */ 53 | private EHAErrorCodeEnum(final String code, final String description) { 54 | this.code = code; 55 | this.description = description; 56 | } 57 | 58 | /** 59 | * 根据编码查询枚举。 60 | * 61 | * @param code 编码。 62 | * @return 枚举。 63 | */ 64 | public static EHAErrorCodeEnum getByCode(String code) { 65 | for (EHAErrorCodeEnum value : EHAErrorCodeEnum.values()) { 66 | if (StringUtils.equals(code, value.getCode())) { 67 | return value; 68 | } 69 | } 70 | return UNSPECIFIED; 71 | } 72 | 73 | /** 74 | * 枚举是否包含此code 75 | * @param code 枚举code 76 | * @return 结果 77 | */ 78 | public static Boolean contains(String code){ 79 | for (EHAErrorCodeEnum value : EHAErrorCodeEnum.values()) { 80 | if (StringUtils.equals(code, value.getCode())) { 81 | return true; 82 | } 83 | } 84 | return false; 85 | } 86 | 87 | @Override 88 | public String getCode() { 89 | return code; 90 | } 91 | 92 | @Override 93 | public String getDescription() { 94 | return description; 95 | } 96 | } -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/Asset.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import lombok.ToString; 7 | 8 | import java.io.Serializable; 9 | import java.math.BigDecimal; 10 | 11 | /** 12 | * 合约账户信息类 13 | * @author yuanfeng.z 14 | * @date 2019/6/28 11:37 15 | */ 16 | @Getter 17 | @Setter 18 | @ToString 19 | @EqualsAndHashCode 20 | public class Asset implements Serializable { 21 | 22 | private static final long serialVersionUID = 1806860024261844247L; 23 | 24 | /** 25 | * 原始数据,以防定义字段不够用 26 | */ 27 | private String originData; 28 | 29 | /** 30 | * 可用余额 31 | */ 32 | private BigDecimal balance; 33 | 34 | /** 35 | * 冻结金额 36 | */ 37 | private BigDecimal freeze; 38 | 39 | /** 40 | * profit 41 | */ 42 | private BigDecimal profit; 43 | 44 | /** 45 | * 总余额 46 | */ 47 | private BigDecimal totalBalance; 48 | 49 | /** 50 | * btc价值 51 | */ 52 | private BigDecimal BTCValue; 53 | 54 | /** 55 | * cny价值 56 | */ 57 | private BigDecimal CNYValue; 58 | 59 | /** 60 | * usdt价值 61 | */ 62 | private BigDecimal USDValue; 63 | 64 | /** 65 | * 保证金 66 | */ 67 | private BigDecimal margin; 68 | 69 | /** 70 | * 冻结保证金 71 | */ 72 | private BigDecimal imargin; 73 | 74 | /** 75 | * btc保证金 76 | */ 77 | private BigDecimal BTCMargin; 78 | 79 | /** 80 | * btc可转 81 | */ 82 | private BigDecimal BTCTransfer; 83 | 84 | /** 85 | * btc可用 86 | */ 87 | private BigDecimal BTCAvailable; 88 | 89 | /** 90 | * btc冻结 91 | */ 92 | private BigDecimal BTCFrozen; 93 | 94 | /** 95 | * btc总余额 96 | */ 97 | private BigDecimal BTCTotalBalance; 98 | 99 | /** 100 | * BCH保证金 101 | */ 102 | private BigDecimal BCHMargin; 103 | 104 | /** 105 | * BCH可转 106 | */ 107 | private BigDecimal BCHTransfer; 108 | 109 | /** 110 | * BCH可用 111 | */ 112 | private BigDecimal BCHAvailable; 113 | 114 | /** 115 | * BCH冻结 116 | */ 117 | private BigDecimal BCHFrozen; 118 | 119 | /** 120 | * BCH总余额 121 | */ 122 | private BigDecimal BCHTotalBalance; 123 | 124 | /** 125 | * ETH保证金 126 | */ 127 | private BigDecimal ETHMargin; 128 | 129 | /** 130 | * ETH可转 131 | */ 132 | private BigDecimal ETHTransfer; 133 | 134 | /** 135 | * ETH可用 136 | */ 137 | private BigDecimal ETHAvailable; 138 | 139 | /** 140 | * ETH冻结 141 | */ 142 | private BigDecimal ETHFrozen; 143 | 144 | /** 145 | * ETH总余额 146 | */ 147 | private BigDecimal ETHTotalBalance; 148 | 149 | } 150 | -------------------------------------------------------------------------------- /trade/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | easy-quant 7 | com.zyf 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | trade 13 | 14 | 15 | 1.0.0 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | commons-httpclient 28 | commons-httpclient 29 | 3.1 30 | compile 31 | 32 | 33 | com.zyf 34 | baseservice 35 | 1.0-SNAPSHOT 36 | compile 37 | 38 | 39 | junit 40 | junit 41 | 4.12 42 | test 43 | 44 | 45 | mysql 46 | mysql-connector-java 47 | 5.1.46 48 | compile 49 | 50 | 51 | com.google.guava 52 | guava 53 | 28.2-jre 54 | compile 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | maven-assembly-plugin 63 | 64 | 65 | jar-with-dependencies 66 | 67 | 68 | 69 | 70 | make-assembly 71 | package 72 | 73 | single 74 | 75 | 76 | 77 | 78 | 79 | 80 | trade-${jar.version} 81 | 82 | 83 | -------------------------------------------------------------------------------- /baseservice/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | logback 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | ${log.level} 20 | 21 | 22 | 23 | UTF-8 24 | %d{yyyy-MM-dd HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36}.%M\(%line\) - %msg%n 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | ${log.path}/${log.level}.log 33 | 34 | 35 | UTF-8 36 | %d{yyyy-MM-dd HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36}.%M\(%line\) - %msg%n 37 | 38 | 39 | 40 | 41 | ${log.level} 42 | 43 | 44 | 45 | 46 | 30 47 | 48 | ${log.path}/${log.level}/${log.level}-%d{yyyy-MM-dd}.%i.log.gz 49 | 50 | 100MB 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | debug 65 | 66 | 67 | UTF-8 68 | %d{yyyy-MM-dd HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36}.%M\(%line\) - %msg%n 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /marketdata/src/main/java/com/zyf/marketdata/proxy/MdExchangeProxy.java: -------------------------------------------------------------------------------- 1 | package com.zyf.marketdata.proxy; 2 | 3 | import com.zyf.baseservice.IMdExchange; 4 | import com.zyf.baseservice.model.enums.CacheNameEnum; 5 | import com.zyf.common.model.Depth; 6 | import com.zyf.common.model.Precision; 7 | import com.zyf.common.model.Ticker; 8 | import com.zyf.common.model.enums.ExchangeEnum; 9 | import com.zyf.common.model.enums.SecuritiesTypeEnum; 10 | import com.zyf.common.util.EhcacheUtil; 11 | import com.zyf.common.util.CommomUtil; 12 | import com.zyf.marketdata.factory.MdExchangeFactory; 13 | import lombok.EqualsAndHashCode; 14 | import lombok.Getter; 15 | import lombok.ToString; 16 | 17 | import java.util.Map; 18 | 19 | /** 20 | * 行情代理类(1.异常统一处理。2.缓存。3.多次获取) 21 | * 22 | * @author yuanfeng.z 23 | * @date 2019/7/4 11:53 24 | */ 25 | @Getter 26 | @ToString 27 | @EqualsAndHashCode 28 | public class MdExchangeProxy { 29 | /** 30 | * 交易交易所对象 31 | */ 32 | private IMdExchange mdExchange; 33 | 34 | /** 35 | * 交易所名称(枚举) 36 | */ 37 | private ExchangeEnum exchangeNameEnum; 38 | 39 | /** 40 | * 交易所名字 41 | */ 42 | private String exchangeName; 43 | 44 | public MdExchangeProxy(ExchangeEnum name, SecuritiesTypeEnum type) { 45 | this.mdExchange = MdExchangeFactory.createMdExchange(name, type); 46 | this.exchangeNameEnum = name; 47 | this.exchangeName = name.getValue(); 48 | EhcacheUtil.initCacheManager(); 49 | EhcacheUtil.createCache(CacheNameEnum.TICKER.getValue(), String.class, Ticker.class); 50 | EhcacheUtil.createCache(CacheNameEnum.DEPTH.getValue(), String.class, Depth.class); 51 | } 52 | 53 | public MdExchangeProxy(String exchangeName, String type) { 54 | this(CommomUtil.toExchangeEnum(exchangeName), CommomUtil.toSecuritiesTypeEnum(type)); 55 | } 56 | 57 | /** 58 | * 获取ticker 59 | * 60 | * @param symbol 币对 61 | * @return 62 | */ 63 | public Ticker getTicker(String symbol) { 64 | Ticker ticker = (Ticker) EhcacheUtil.get(CacheNameEnum.TICKER.getValue(), symbol); 65 | if (ticker == null) { 66 | ticker = this.mdExchange.getTicker(symbol); 67 | if (ticker != null) { 68 | EhcacheUtil.put(CacheNameEnum.TICKER.getValue(), symbol, ticker); 69 | } 70 | } 71 | return ticker; 72 | } 73 | 74 | /** 75 | * 获取深度 76 | * 77 | * @param symbol 币对 78 | * @return 79 | */ 80 | public Depth getDepth(String symbol) { 81 | Depth depth = (Depth) EhcacheUtil.get(CacheNameEnum.DEPTH.getValue(), symbol); 82 | if (depth == null) { 83 | depth = this.mdExchange.getDepth(symbol); 84 | if (depth != null) { 85 | EhcacheUtil.put(CacheNameEnum.DEPTH.getValue(), symbol, depth); 86 | } 87 | } 88 | return depth; 89 | } 90 | 91 | /** 92 | * 获取精度 93 | * 94 | * @return 95 | */ 96 | public Map getPrecisions() { 97 | Map precisionMap = this.mdExchange.getPrecisions(); 98 | return precisionMap; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /framework/src/main/java/com/zyf/framework/service/impl/EmailServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.zyf.framework.service.impl; 2 | 3 | import com.sun.mail.util.MailSSLSocketFactory; 4 | import com.zyf.framework.service.IEmailService; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.thymeleaf.TemplateEngine; 7 | import org.thymeleaf.context.Context; 8 | 9 | import javax.mail.*; 10 | import javax.mail.internet.InternetAddress; 11 | import javax.mail.internet.MimeMessage; 12 | import java.io.File; 13 | import java.util.Date; 14 | import java.util.List; 15 | import java.util.Properties; 16 | 17 | 18 | /** 19 | * 邮件服务 20 | * 21 | * @author yuanfeng.z 22 | * @date 2019/11/15 17:15 23 | */ 24 | @Slf4j 25 | public class EmailServiceImpl implements IEmailService { 26 | 27 | public static void sendMail(String host, 28 | String user, 29 | String password, 30 | String fromMail, 31 | String toMail, 32 | String mailTitle, 33 | String mailContent) { 34 | 35 | // 1.创建连接对象javax.mail.Session 36 | // 2.创建邮件对象 javax.mail.Message 37 | // 3.发送一封激活邮件 38 | 39 | // 获取系统属性 40 | Properties properties = System.getProperties(); 41 | // 设置邮件服务器 42 | properties.setProperty("mail.smtp.host", host); 43 | // 打开认证 44 | properties.setProperty("mail.smtp.auth", "true"); 45 | 46 | try { 47 | MailSSLSocketFactory sf = new MailSSLSocketFactory(); 48 | sf.setTrustAllHosts(true); 49 | properties.put("mail.smtp.ssl.enable", "true"); 50 | properties.put("mail.smtp.ssl.socketFactory", sf); 51 | 52 | // 1.获取默认session对象 53 | Session session = Session.getDefaultInstance(properties, new Authenticator() { 54 | @Override 55 | public PasswordAuthentication getPasswordAuthentication() { 56 | // 发件人邮箱账号、授权码 57 | return new PasswordAuthentication(user, password); 58 | } 59 | }); 60 | 61 | // 2.创建邮件对象 62 | Message message = new MimeMessage(session); 63 | // 2.1设置发件人 64 | message.setFrom(new InternetAddress(fromMail)); 65 | // 2.2设置接收人 66 | message.addRecipient(Message.RecipientType.TO, new InternetAddress(toMail)); 67 | // 2.3设置邮件主题 68 | message.setSubject(mailTitle); 69 | // 2.4设置邮件内容 70 | message.setContent(mailContent, "text/html;charset=UTF-8"); 71 | // 3.发送邮件 72 | Transport.send(message); 73 | System.out.println("邮件成功发送!"); 74 | } catch (Exception e) { 75 | e.printStackTrace(); 76 | } 77 | } 78 | 79 | public static void main(String[] args) { 80 | String host = "smtpdm.xxx.com"; 81 | String fromMail = "email@xxx.cc"; 82 | String user = "email@xxx.cc"; 83 | String password = "xxxx"; 84 | String toMail = "xxxx@qq.com"; 85 | String mailTitle = "etwet"; 86 | String mailContent = "fssd"; 87 | try { 88 | EmailServiceImpl.sendMail(host, user, password, fromMail, toMail, mailTitle, mailContent); 89 | } catch (Exception e) { 90 | e.printStackTrace(); 91 | } 92 | } 93 | } -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/exceptions/ExchangeHttpApiException.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.exceptions; 2 | 3 | import lombok.Data; 4 | import lombok.EqualsAndHashCode; 5 | 6 | /** 7 | * Description:Exchange Http Api Exception 8 | * @author yuanfeng.z 9 | * @date 2019/6/25 10:27 10 | * @see RuntimeException 11 | */ 12 | @Data 13 | @EqualsAndHashCode(callSuper=false) 14 | public class ExchangeHttpApiException extends RuntimeException { 15 | 16 | private static final long serialVersionUID = -7864604160297181941L; 17 | 18 | /** 错误码 */ 19 | protected final ErrorCode errorCode; 20 | 21 | /** 22 | * 这个是和谐一些不必要的地方,冗余的字段 23 | * 尽量不要用 24 | */ 25 | private String code; 26 | 27 | /** 28 | * 无参默认构造UNSPECIFIED 29 | */ 30 | public ExchangeHttpApiException() { 31 | super(EHAErrorCodeEnum.UNSPECIFIED.getDescription()); 32 | this.errorCode = EHAErrorCodeEnum.UNSPECIFIED; 33 | } 34 | 35 | /** 36 | * 指定错误码构造通用异常 37 | * @param errorCode 错误码 38 | */ 39 | public ExchangeHttpApiException(final ErrorCode errorCode) { 40 | super(errorCode.getDescription()); 41 | this.errorCode = errorCode; 42 | } 43 | 44 | /** 45 | * 指定详细描述构造通用异常 46 | * @param detailedMessage 详细描述 47 | */ 48 | public ExchangeHttpApiException(final String detailedMessage) { 49 | super(detailedMessage); 50 | this.errorCode = EHAErrorCodeEnum.UNSPECIFIED; 51 | } 52 | 53 | /** 54 | * 指定导火索构造通用异常 55 | * @param t 导火索 56 | */ 57 | public ExchangeHttpApiException(final Throwable t) { 58 | super(t); 59 | this.errorCode = EHAErrorCodeEnum.UNSPECIFIED; 60 | } 61 | 62 | /** 63 | * 构造通用异常 64 | * @param errorCode 错误码 65 | * @param detailedMessage 详细描述 66 | */ 67 | public ExchangeHttpApiException(final ErrorCode errorCode, final String detailedMessage) { 68 | super(detailedMessage); 69 | this.errorCode = errorCode; 70 | } 71 | 72 | /** 73 | * 构造通用异常 74 | * @param errorCode 错误码 75 | * @param t 导火索 76 | */ 77 | public ExchangeHttpApiException(final ErrorCode errorCode, final Throwable t) { 78 | super(errorCode.getDescription(), t); 79 | this.errorCode = errorCode; 80 | } 81 | 82 | /** 83 | * 构造通用异常 84 | * @param detailedMessage 详细描述 85 | * @param t 导火索 86 | */ 87 | public ExchangeHttpApiException(final String detailedMessage, final Throwable t) { 88 | super(detailedMessage, t); 89 | this.errorCode = EHAErrorCodeEnum.UNSPECIFIED; 90 | } 91 | 92 | /** 93 | * 构造通用异常 94 | * @param errorCode 错误码 95 | * @param detailedMessage 详细描述 96 | * @param t 导火索 97 | */ 98 | public ExchangeHttpApiException(final ErrorCode errorCode, final String detailedMessage, 99 | final Throwable t) { 100 | super(detailedMessage, t); 101 | this.errorCode = errorCode; 102 | } 103 | 104 | /** 105 | * Getter method for property errorCode. 106 | * 107 | * @return property value of errorCode 108 | */ 109 | public ErrorCode getErrorCode() { 110 | return errorCode; 111 | } 112 | 113 | 114 | public static void main(String[] args) { 115 | String s=new String("quantity_low\n") 116 | //.replaceAll("String symbol","\"1200\",\"\"") 117 | .toUpperCase(); 118 | System.out.print(s); 119 | } 120 | } -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/okhttp/OkHttpV3ClientProxy.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.okhttp; 2 | 3 | import com.zyf.common.exceptions.ExTimeOutException; 4 | import com.zyf.common.http.HttpUtil; 5 | import lombok.extern.slf4j.Slf4j; 6 | 7 | import java.io.IOException; 8 | import java.net.ConnectException; 9 | import java.net.SocketTimeoutException; 10 | import java.util.HashMap; 11 | import java.util.LinkedHashMap; 12 | import java.util.Map; 13 | 14 | /** 15 | * okhttpV3代理类(用于处理业务异常) 16 | * 17 | * @author yuanfeng.z 18 | * @date 2019/7/11 15:51 19 | */ 20 | @Slf4j 21 | public class OkHttpV3ClientProxy { 22 | private static OkHttpV3ClientProxy okHttpV3ClientProxy = null; 23 | 24 | public static OkHttpV3ClientProxy getOkHttpV3ClientProxy() { 25 | if (okHttpV3ClientProxy == null) { 26 | synchronized (OkHttpV3ClientProxy.class) { 27 | if (okHttpV3ClientProxy == null) { 28 | okHttpV3ClientProxy = new OkHttpV3ClientProxy(); 29 | } 30 | } 31 | } 32 | return okHttpV3ClientProxy; 33 | } 34 | 35 | public static String get(String url) { 36 | try { 37 | return OkHttpV3Client.get(url); 38 | } catch (SocketTimeoutException | ConnectException e) { 39 | throw new ExTimeOutException("connect exchange time out"); 40 | } catch (IOException e) { 41 | e.printStackTrace(); 42 | } 43 | return null; 44 | } 45 | 46 | public static String post(String url, HashMap paramsMap) { 47 | try { 48 | return HttpUtil.doPost(url,paramsMap); 49 | } catch (Exception e) { 50 | log.error(e.getMessage()); 51 | } 52 | return null; 53 | } 54 | 55 | public static String get(String url, String headerName, String headerValue) { 56 | try { 57 | return OkHttpV3Client.get(url, headerName, headerValue); 58 | } catch (SocketTimeoutException | ConnectException e) { 59 | throw new ExTimeOutException("connect exchange time out"); 60 | } catch (IOException e) { 61 | e.printStackTrace(); 62 | } 63 | return null; 64 | } 65 | 66 | public static String get(String url, Map headers) { 67 | return OkHttpV3Client.get(url, headers); 68 | } 69 | 70 | public static String getHeader(String url, LinkedHashMap lh) { 71 | return OkHttpV3Client.getHeader(url, lh); 72 | } 73 | 74 | public static String postHeader(String url, LinkedHashMap lh, String data) { 75 | return OkHttpV3Client.postHeader(url, lh, data); 76 | } 77 | 78 | public static String post(String url, String data) { 79 | return OkHttpV3Client.post(url, data); 80 | } 81 | 82 | public static String post(String url, String data, String headerName, String headerValue) { 83 | return OkHttpV3Client.post(url, data, headerName, headerValue); 84 | } 85 | 86 | public static String post(String url, String data, Map headers) { 87 | return OkHttpV3Client.post(url, data, headers); 88 | } 89 | 90 | public static String delete(String url) { 91 | return OkHttpV3Client.delete(url); 92 | } 93 | 94 | public static String delete(String url, String headerName, String headerValue) { 95 | return OkHttpV3Client.delete(url, headerName, headerValue); 96 | } 97 | 98 | public static String delete(String url, Map headers) { 99 | return OkHttpV3Client.delete(url, headers); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /marketdata/src/main/java/com/zyf/marketdata/http/stock/OkexMdExchange.java: -------------------------------------------------------------------------------- 1 | package com.zyf.marketdata.http.stock; 2 | 3 | import com.alibaba.fastjson.JSONArray; 4 | import com.alibaba.fastjson.JSONObject; 5 | import com.zyf.baseservice.IMdExchange; 6 | import com.zyf.baseservice.util.okex.OkexUtil; 7 | import com.zyf.common.model.Depth; 8 | import com.zyf.common.model.Kline; 9 | import com.zyf.common.model.Precision; 10 | import com.zyf.common.model.Ticker; 11 | import com.zyf.common.model.enums.ExchangeEnum; 12 | import com.zyf.common.okhttp.OkHttpV3ClientProxy; 13 | 14 | import java.util.List; 15 | import java.util.Map; 16 | 17 | 18 | /** 19 | * okexV3交易所实现类 20 | * @author yuanfeng.z 21 | * @date 2019/6/27 10:02 22 | */ 23 | public class OkexMdExchange implements IMdExchange { 24 | 25 | /** 26 | * 协议 27 | */ 28 | private static final String PROTOCOL = "https://"; 29 | 30 | /** 31 | * 网站 32 | */ 33 | private static final String SITE = "www.okex.com"; 34 | 35 | /** 36 | * url 37 | */ 38 | private static final String URL = PROTOCOL +SITE; 39 | 40 | /** 41 | * get请求方法 42 | */ 43 | private static final String METHOD_GET = "GET"; 44 | 45 | /** 46 | * 交易所名字 47 | */ 48 | private final ExchangeEnum name = ExchangeEnum.OKEXV3; 49 | 50 | /** 51 | * 价格、数量精度资源路径 52 | */ 53 | private static final String PRECISION = "/api/spot/v3/instruments"; 54 | 55 | /** 56 | * ticker资源路径 57 | */ 58 | private static final String TICKER = "/api/spot/v3/instruments/{symbol}/ticker"; 59 | 60 | /** 61 | * depth资源路径 62 | */ 63 | private static final String DEPTH = "/api/spot/v3/instruments/{symbol}/book"; 64 | 65 | /** 66 | * 单例模式 67 | * @return 68 | */ 69 | public static OkexMdExchange okexMdExchange = new OkexMdExchange(); 70 | public static OkexMdExchange getInstance() { 71 | return okexMdExchange; 72 | } 73 | 74 | @Override 75 | public Ticker getTicker(String symbol) { 76 | // 转换币对格式 77 | symbol = OkexUtil.transfSymbol(symbol); 78 | 79 | /*获取ticker数据*/ 80 | StringBuilder sb = new StringBuilder(); 81 | String ticker = TICKER.replace("{symbol}", symbol); 82 | sb.append(URL).append(ticker); 83 | String tickerStr = OkHttpV3ClientProxy.get(sb.toString()); 84 | 85 | /*适配*/ 86 | JSONObject jo = JSONObject.parseObject(tickerStr); 87 | return OkexUtil.parseTicker(jo); 88 | } 89 | 90 | @Override 91 | public List getKline(String symbol, String granularity) { 92 | return null; 93 | } 94 | 95 | @Override 96 | public Depth getDepth(String symbol) { 97 | // 转换币对格式 98 | symbol = OkexUtil.transfSymbol(symbol); 99 | 100 | /*获取depth数据*/ 101 | StringBuilder sb = new StringBuilder(); 102 | final int size = 20; 103 | String depth = DEPTH.replace("{symbol}", symbol); 104 | sb.append(URL).append(depth).append("?").append("size=").append(size); 105 | String depthStr = OkHttpV3ClientProxy.get(sb.toString()); 106 | 107 | /*适配*/ 108 | JSONObject jo = JSONObject.parseObject(depthStr); 109 | return OkexUtil.parseDepth(jo); 110 | } 111 | 112 | /** 113 | * 获取币对精度 114 | * @return 币对精度列表 115 | */ 116 | @Override 117 | public Map getPrecisions() { 118 | /*获取币种精度数据*/ 119 | StringBuilder sb = new StringBuilder(); 120 | sb.append(URL).append(PRECISION); 121 | String str = OkHttpV3ClientProxy.get(sb.toString()); 122 | 123 | /*适配*/ 124 | JSONArray jo = JSONObject.parseArray(str); 125 | Map map = OkexUtil.parsePrecisions(jo); 126 | return map; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /strategy/src/main/java/com/zyf/strategy/GridStrategy.java: -------------------------------------------------------------------------------- 1 | package com.zyf.strategy; 2 | 3 | import com.zyf.common.model.Depth; 4 | import com.zyf.common.model.Order; 5 | import com.zyf.common.util.MathUtil; 6 | import com.zyf.framework.boot.BaseStrategy; 7 | import com.zyf.framework.scheduling.interfaces.ScheduledByZyf; 8 | import lombok.extern.slf4j.Slf4j; 9 | 10 | import java.math.BigDecimal; 11 | import java.math.RoundingMode; 12 | import java.util.List; 13 | 14 | /** 15 | * 网格策略 16 | * @author yuanfeng.z 17 | * @date 2020/7/27 1:44 18 | */ 19 | @Slf4j 20 | public class GridStrategy extends BaseStrategy { 21 | 22 | /** 23 | * 挂单之间差额 24 | */ 25 | private BigDecimal spreadRate = new BigDecimal(0.03); 26 | 27 | /** 28 | * btc-usd合约最小单位 29 | */ 30 | private BigDecimal minUtil = new BigDecimal("0.1"); 31 | 32 | /** 33 | * 挂单数量(委托和计划) 34 | */ 35 | private int orderNum = 0; 36 | 37 | @Override 38 | protected void init() { 39 | log.info("init"); 40 | 41 | // 撤单 42 | tradeE.cancelAll(this.symbol); 43 | tradeE.triggerCancelAll(symbol); 44 | //.getTriggerPendingOrders(symbol); 45 | } 46 | 47 | @Override 48 | protected void recovery() { 49 | 50 | } 51 | 52 | @ScheduledByZyf(cron = "*/1 * * * * ?") 53 | private void checkPendingOrder() { 54 | // 获取挂单 55 | List orders = tradeE.getPendingOrders(this.symbol); 56 | orders.addAll(tradeE.getTriggerPendingOrders(this.symbol)); 57 | this.orderNum = orders.size(); 58 | if ( 1 <= this.orderNum && this.orderNum <= 2) { 59 | // 撤单 60 | tradeE.cancelAll(this.symbol); 61 | tradeE.triggerCancelAll(symbol); 62 | } 63 | } 64 | 65 | @Override 66 | @ScheduledByZyf(cron = "*/1 * * * * ?") 67 | // @ScheduledByZyf(initialDelay = 0, fixedDelay = 1000) 68 | protected void run() { 69 | // 挂单 70 | Depth d = mdE.getDepth(this.symbol); 71 | log.info(d.toString()); 72 | BigDecimal askPrice = d.getAsks().get(0).getPrice(); 73 | BigDecimal bidPrice = d.getBids().get(0).getPrice(); 74 | // 获取挂单 75 | List orders = tradeE.getPendingOrders(this.symbol); 76 | orders.addAll(tradeE.getTriggerPendingOrders(this.symbol)); 77 | if ( 1 <= orders.size() && orders.size() <= 2) { 78 | // 撤单 79 | tradeE.cancelAll(this.symbol); 80 | tradeE.triggerCancelAll(this.symbol); 81 | } 82 | 83 | if (this.orderNum == 0) { 84 | // 止损 85 | BigDecimal price = bidPrice.multiply(BigDecimal.ONE.subtract(spreadRate.multiply(new BigDecimal("2")))).setScale(1, RoundingMode.UP); 86 | price = MathUtil.adjustMinUtil(price, minUtil, RoundingMode.UP); 87 | id = tradeE.triggerCloseLong(this.symbol, price, new BigDecimal("1"), 1); 88 | price = askPrice.multiply(BigDecimal.ONE.add(spreadRate.multiply(new BigDecimal("2")))).setScale(1, RoundingMode.DOWN); 89 | price = MathUtil.adjustMinUtil(price, minUtil, RoundingMode.DOWN); 90 | id = tradeE.triggerCloseShort(this.symbol, price, new BigDecimal("1"), 1); 91 | 92 | // 下单 93 | price = bidPrice.multiply(BigDecimal.ONE.subtract(spreadRate)).setScale(1, RoundingMode.DOWN);; 94 | price = MathUtil.adjustMinUtil(price, minUtil, RoundingMode.DOWN); 95 | String id = tradeE.openLong(this.symbol, price, new BigDecimal("1"), 1); 96 | price = askPrice.multiply(BigDecimal.ONE.add(spreadRate)).setScale(1, RoundingMode.UP); 97 | price = MathUtil.adjustMinUtil(price, minUtil, RoundingMode.UP); 98 | id = tradeE.closeLong(this.symbol, price, new BigDecimal("1"), 1); 99 | } 100 | 101 | 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/http/HttpParameter.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model.http; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | 5 | import java.io.Serializable; 6 | import java.util.Comparator; 7 | import java.util.LinkedHashMap; 8 | import java.util.Map; 9 | import java.util.Objects; 10 | import java.util.function.Function; 11 | 12 | /** 13 | * HTTP请求参数 14 | * 15 | * @author yuanfeng.z 16 | * @date 2019-06-27 17 | */ 18 | public class HttpParameter extends LinkedHashMap implements Serializable { 19 | 20 | private HttpParameter() { 21 | } 22 | 23 | /** 24 | * 构造器 25 | * 26 | * @return 实例对象 27 | */ 28 | public static HttpParameter build() { 29 | return new HttpParameter(); 30 | } 31 | 32 | /** 33 | * 构造器 34 | * 35 | * @param key 键 36 | * @param value 值 37 | * @return 实例对象 38 | */ 39 | public static HttpParameter build(String key, Object value) { 40 | HttpParameter parameter = new HttpParameter(); 41 | parameter.put(key, value); 42 | return parameter; 43 | } 44 | 45 | /** 46 | * 添加键值对 47 | * 48 | * @param key 键 49 | * @param value 值 50 | * @return 本实例对象 51 | */ 52 | public HttpParameter add(String key, Object value) { 53 | super.put(key, value); 54 | return this; 55 | } 56 | 57 | /** 58 | * 排序 59 | * 60 | * @param comparator 比较器 61 | * @return 本实例对象 62 | */ 63 | public HttpParameter sort(Comparator comparator) { 64 | HttpParameter parameter = new HttpParameter(); 65 | this.keySet().stream() 66 | .sorted(comparator) 67 | .forEach(k -> parameter.add(k, this.get(k))); 68 | this.clear(); 69 | parameter.forEach(this::add); 70 | return this; 71 | } 72 | 73 | /** 74 | * 排序,默认按字符串ASCII排序 75 | * 76 | * @return 本实例对象 77 | */ 78 | public HttpParameter sort() { 79 | return sort(String::compareTo); 80 | } 81 | 82 | /** 83 | * 连接 84 | * 85 | * @param delimiter 键和值之间的符号 86 | * @param join 每对键值之间的符号 87 | * @param encode 编码函数 88 | * @return 请求参数连接结果 89 | */ 90 | public String concat(String delimiter, String join, Function encode) { 91 | Objects.requireNonNull(delimiter, "delimiter"); 92 | Objects.requireNonNull(join, "join"); 93 | if (null == encode) { 94 | encode = Object::toString; 95 | } 96 | StringBuilder sb = new StringBuilder(); 97 | Function finalEncode = encode; 98 | this.forEach((k, v) -> sb.append(k).append(delimiter) 99 | .append(finalEncode.apply(v)).append(join)); 100 | String result = sb.toString(); 101 | if (0 < sb.length()) { 102 | result = result.substring(0, result.length() - join.length()); 103 | } 104 | return result; 105 | } 106 | 107 | /** 108 | * 连接 109 | * 110 | * @param encode 编码函数 111 | * @return 连接结果 112 | */ 113 | public String concat(Function encode) { 114 | return concat("=", "&", encode); 115 | } 116 | 117 | /** 118 | * 连接 119 | * 120 | * @return 连接结果 121 | */ 122 | public String concat() { 123 | return concat("=", "&", null); 124 | } 125 | 126 | /** 127 | * 转换json格式 128 | * 129 | * @param function 转换函数 130 | * @return json字符串对象 131 | */ 132 | public String json(Function function) { 133 | return function.apply(this); 134 | } 135 | 136 | /** 137 | * 转换json格式 138 | * 139 | * @return 140 | */ 141 | public String json() { 142 | return JSONObject.toJSONString(this); 143 | } 144 | 145 | } 146 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/http/HttpUtil.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.http; 2 | 3 | import org.apache.http.HttpEntity; 4 | import org.apache.http.HttpHost; 5 | import org.apache.http.HttpResponse; 6 | import org.apache.http.NameValuePair; 7 | import org.apache.http.client.ClientProtocolException; 8 | import org.apache.http.client.CookieStore; 9 | import org.apache.http.client.HttpClient; 10 | import org.apache.http.client.entity.UrlEncodedFormEntity; 11 | import org.apache.http.client.methods.HttpGet; 12 | import org.apache.http.client.methods.HttpPost; 13 | import org.apache.http.impl.client.BasicCookieStore; 14 | import org.apache.http.impl.client.CloseableHttpClient; 15 | import org.apache.http.impl.client.HttpClients; 16 | import org.apache.http.message.BasicNameValuePair; 17 | import org.apache.http.util.EntityUtils; 18 | 19 | import java.io.IOException; 20 | import java.io.UnsupportedEncodingException; 21 | import java.util.ArrayList; 22 | import java.util.List; 23 | import java.util.Map; 24 | 25 | /** 26 | * HTTP工具类 27 | * 28 | * @author yuanfeng.z 29 | * @date 2020/7/27 21:44 30 | */ 31 | public class HttpUtil { 32 | 33 | /** 34 | * doGet 35 | * 36 | * @param url 37 | * @return 38 | */ 39 | public static String doGet(String url) 40 | { 41 | CloseableHttpClient httpclient = HttpClients.createDefault(); 42 | HttpGet get = new HttpGet(url); 43 | String body = null; 44 | try 45 | { 46 | HttpResponse httpresponse = httpclient.execute(get); 47 | HttpEntity entity = httpresponse.getEntity(); 48 | body = EntityUtils.toString(entity); 49 | } catch (ClientProtocolException e) 50 | { 51 | // TODO Auto-generated catch block 52 | e.printStackTrace(); 53 | } catch (IOException e) 54 | { 55 | // TODO Auto-generated catch block 56 | e.printStackTrace(); 57 | } 58 | fmtOut(url, body); 59 | return body; 60 | } 61 | 62 | /** 63 | * doPost 64 | * 65 | * @param url 66 | * @param parms 67 | * @return 68 | */ 69 | public static String doPost(String url, Map parms) 70 | { 71 | CookieStore cookieStore = new BasicCookieStore(); 72 | //cookieStore.addCookie(cookie); 73 | HttpClient httpClient = HttpClients.custom().setDefaultCookieStore(cookieStore) 74 | //todo 代理,注意上线打包关闭 75 | // .setProxy(new HttpHost("127.0.0.1", 7890)) 76 | .build(); 77 | HttpPost post = new HttpPost(url); 78 | String body = null; 79 | try 80 | { 81 | List pairs = new ArrayList<>(); 82 | for (String key : parms.keySet()) 83 | { 84 | pairs.add(new BasicNameValuePair(key, parms.get(key))); 85 | } 86 | post.setEntity(new UrlEncodedFormEntity(pairs, "UTF-8")); 87 | HttpResponse httpresponse = httpClient.execute(post); 88 | HttpEntity responseEntity = httpresponse.getEntity(); 89 | body = EntityUtils.toString(responseEntity); 90 | return body; 91 | } catch (UnsupportedEncodingException e) 92 | { 93 | // TODO Auto-generated catch block 94 | e.printStackTrace(); 95 | } catch (ClientProtocolException e) 96 | { 97 | // TODO Auto-generated catch block 98 | e.printStackTrace(); 99 | } catch (IOException e) 100 | { 101 | // TODO Auto-generated catch block 102 | e.printStackTrace(); 103 | } 104 | return null; 105 | } 106 | 107 | public static void fmtOut(String url, String ret) 108 | { 109 | System.out.println("==============start================="); 110 | System.out.println(String.format("request url=%s", url)); 111 | System.out.println("methd:GET"); 112 | System.out.println(String.format("response %s", ret)); 113 | System.out.println("==============end==================="); 114 | } 115 | 116 | public static void fmtOut(String url, String parms, String ret) 117 | { 118 | System.out.println("==============start================="); 119 | System.out.println(String.format("request url=%s", url)); 120 | System.out.println("methd:POST"); 121 | System.out.println(String.format("parms: %s", parms)); 122 | System.out.println(String.format("response %s", ret)); 123 | System.out.println("==============end==================="); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.zyf 8 | easy-quant 9 | pom 10 | 1.0-SNAPSHOT 11 | 12 | framework 13 | strategy 14 | trade 15 | marketdata 16 | common 17 | baseservice 18 | 19 | 20 | 21 | UTF-8 22 | 1.8 23 | 24 | 25 | 26 | 27 | 28 | 29 | org.slf4j 30 | slf4j-api 31 | 1.7.20 32 | 33 | 34 | 35 | ch.qos.logback 36 | logback-classic 37 | 1.2.3 38 | 39 | 40 | 41 | ch.qos.logback 42 | logback-core 43 | 1.2.3 44 | 45 | 46 | 47 | org.projectlombok 48 | lombok 49 | 1.18.12 50 | provided 51 | 52 | 53 | 54 | com.alibaba 55 | fastjson 56 | 1.2.72 57 | 58 | 59 | 60 | org.apache.commons 61 | commons-lang3 62 | 3.8.1 63 | 64 | 65 | 66 | 67 | 68 | 69 | org.apache.maven.plugins 70 | maven-compiler-plugin 71 | 3.8.0 72 | 73 | 1.8 74 | 1.8 75 | 76 | 77 | 78 | 79 | maven-resources-plugin 80 | 3.1.0 81 | 82 | 83 | copy-resources 84 | 85 | validate 86 | 87 | copy-resources 88 | 89 | 90 | 91 | ${basedir}/target/classes 92 | 93 | 94 | 95 | ${basedir}/../baseservice/src/main/resources 96 | true 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /framework/src/main/java/com/zyf/framework/scheduling/ScheduledTask.java: -------------------------------------------------------------------------------- 1 | package com.zyf.framework.scheduling; 2 | 3 | import org.quartz.*; 4 | import org.quartz.impl.StdSchedulerFactory; 5 | 6 | import java.lang.reflect.Method; 7 | import java.util.Date; 8 | 9 | /** 10 | * 定时任务类 11 | *
建造者模式 12 | * @author yuanfeng.z 13 | * @date 2020/7/25 1:10 14 | */ 15 | public class ScheduledTask { 16 | 17 | /** 18 | * quartz定时任务 19 | */ 20 | private Scheduler scheduler; 21 | 22 | /** 23 | * 策略实例 24 | */ 25 | private Object strategyIns; 26 | 27 | /** 28 | * 策略启动方法 29 | */ 30 | private Method method; 31 | 32 | /** 33 | * 触发器 34 | */ 35 | private Trigger trigger; 36 | 37 | /** 38 | * 定义Job的实例 39 | */ 40 | private JobDetail jobDetail; 41 | 42 | public final static String METHOD = "method"; 43 | 44 | public final static String STRATEGYINS = "strategyIns"; 45 | 46 | /** 47 | * 创建定时任务 48 | * @param strategyIns 策略实例 49 | * @param method 策略启动方法 50 | * @return 51 | */ 52 | public static ScheduledTask newScheduledTask(Object strategyIns, Method method) { 53 | return new ScheduledTask(strategyIns, method); 54 | } 55 | 56 | private ScheduledTask(Object strategyIns, Method method) { 57 | this.strategyIns = strategyIns; 58 | this.method = method; 59 | } 60 | 61 | /** 62 | * 创建quartz定时任务实例 63 | * @return 64 | */ 65 | public ScheduledTask newScheduler() { 66 | try { 67 | this.scheduler = StdSchedulerFactory.getDefaultScheduler(); 68 | } catch (SchedulerException e) { 69 | throw new RuntimeException(e.getMessage()); 70 | } 71 | return this; 72 | } 73 | 74 | /** 75 | * 设置 JobDetail 76 | * @return 77 | */ 78 | public ScheduledTask setJobDetail() { 79 | JobDataMap jobDataMap = new JobDataMap(); 80 | jobDataMap.put(ScheduledTask.METHOD, this.method); 81 | jobDataMap.put(STRATEGYINS, this.strategyIns); 82 | this.jobDetail = JobBuilder.newJob(ScheduledJob.class). 83 | usingJobData(jobDataMap). 84 | build(); 85 | return this; 86 | } 87 | 88 | /** 89 | * 设置延迟触发器 90 | * @param initialDelay 初始延迟时间 91 | * @param fixedDelay 每次轮询相隔延迟时间 92 | * @return 93 | */ 94 | public ScheduledTask setFixedDelayTrigger(long initialDelay, long fixedDelay) { 95 | this.trigger = TriggerBuilder.newTrigger(). 96 | startAt(new Date(System.currentTimeMillis() + initialDelay)). 97 | withSchedule(SimpleScheduleBuilder. 98 | simpleSchedule(). 99 | withIntervalInMilliseconds(fixedDelay). 100 | repeatForever()). 101 | build(); 102 | return this; 103 | } 104 | 105 | /** 106 | * 设置cron触发器 107 | * @param cron cron表达式 108 | * @return 109 | */ 110 | public ScheduledTask setCronTrigger(String cron) { 111 | this.trigger = TriggerBuilder.newTrigger(). 112 | withSchedule(CronScheduleBuilder.cronSchedule(cron)). 113 | build(); 114 | return this; 115 | } 116 | 117 | /** 118 | * 建造者 build 119 | * @return 120 | */ 121 | public ScheduledTask build() { 122 | 123 | try { 124 | this.scheduler.scheduleJob(this.jobDetail, this.trigger); 125 | } catch (SchedulerException e) { 126 | throw new RuntimeException(e.getMessage()); 127 | } 128 | return this; 129 | } 130 | 131 | /** 132 | * 启动定时任务 133 | * @return 134 | */ 135 | public ScheduledTask start() { 136 | try { 137 | this.scheduler.start(); 138 | } catch (SchedulerException e) { 139 | throw new RuntimeException(e.getMessage()); 140 | } 141 | return this; 142 | } 143 | 144 | public void shutdown() throws SchedulerException { 145 | this.scheduler.shutdown(); 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /framework/src/main/java/com/zyf/framework/EasyQuantyApplication.java: -------------------------------------------------------------------------------- 1 | package com.zyf.framework; 2 | 3 | import com.zyf.framework.boot.ApplicationContext; 4 | import com.zyf.framework.boot.BaseStrategy; 5 | import com.zyf.framework.boot.Environment; 6 | import com.zyf.framework.scheduling.ScheduleTaskManager; 7 | import com.zyf.framework.util.StopWatch; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.quartz.SchedulerException; 10 | 11 | import java.lang.management.ManagementFactory; 12 | import java.util.Map; 13 | 14 | @Slf4j 15 | public class EasyQuantyApplication { 16 | 17 | private Class strategyClass; 18 | 19 | ApplicationContext ac = null; 20 | 21 | public EasyQuantyApplication(Class strategySources) { 22 | this.strategyClass = strategySources; 23 | } 24 | 25 | public static void run(Class strategySources, String... args) { 26 | new EasyQuantyApplication(strategySources).run(args); 27 | } 28 | 29 | /** 30 | * 运行入口 31 | * @param args 启动参数 32 | */ 33 | public void run(String... args) { 34 | StopWatch stopWatch = new StopWatch(); 35 | stopWatch.start(); 36 | this.setStrategyClass(this.strategyClass); 37 | ac = new ApplicationContext(this.strategyClass, args); 38 | try { 39 | ac.run(); 40 | } catch (IllegalAccessException e) { 41 | log.error(e.toString()); 42 | throw new RuntimeException(e.getMessage()); 43 | } catch (InstantiationException e) { 44 | log.error(e.toString()); 45 | throw new RuntimeException(e.getMessage()); 46 | } catch (NoSuchFieldException e) { 47 | log.error(e.toString()); 48 | throw new RuntimeException(e.getMessage()); 49 | } catch (Exception e) { 50 | log.error(e.toString()); 51 | throw new RuntimeException(e.getMessage()); 52 | } 53 | 54 | this.shutdownHook(); 55 | stopWatch.stop(); 56 | 57 | log.info(getStartedMessage(stopWatch).toString()); 58 | 59 | } 60 | 61 | public void setStrategyClass(Class strategySources) { 62 | this.strategyClass = strategySources; 63 | } 64 | 65 | private String getApplicationName() { 66 | return (this.strategyClass != null ? this.strategyClass.getName() 67 | : "application"); 68 | } 69 | 70 | private StringBuilder getStartedMessage(StopWatch stopWatch) { 71 | StringBuilder message = new StringBuilder(); 72 | message.append("Started "); 73 | message.append(getApplicationName()); 74 | message.append(" in "); 75 | message.append(stopWatch.getTotalTimeSeconds()); 76 | try { 77 | double uptime = ManagementFactory.getRuntimeMXBean().getUptime() / 1000.0; 78 | message.append(" seconds (JVM running for " + uptime + ")"); 79 | } 80 | catch (Throwable ex) { 81 | // No JVM time available 82 | } 83 | return message; 84 | } 85 | 86 | /** 87 | * 程序退出清理 88 | */ 89 | public void shutdownHook() { 90 | for (Map.Entry pair : ac.getBeanDefinitionMap().entrySet()) { 91 | BaseStrategy baseStrategy = (BaseStrategy)pair.getValue(); 92 | } 93 | Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { 94 | @Override 95 | public void run() 96 | { 97 | log.info("Execute Hook....."); 98 | try { 99 | ScheduleTaskManager.getInstance().shutdown(); 100 | 101 | for (Map.Entry pair : ac.getBeanDefinitionMap().entrySet()) { 102 | BaseStrategy baseStrategy = (BaseStrategy)pair.getValue(); 103 | baseStrategy.destroy(); 104 | } 105 | } catch (SchedulerException e) { 106 | e.printStackTrace(); 107 | } 108 | log.info("Execute Hook Finish"); 109 | } 110 | })); 111 | } 112 | 113 | public ApplicationContext getApplicationContext() { 114 | return ac; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/crypto/HexUtil.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.crypto; 2 | 3 | import java.util.Objects; 4 | 5 | /** 6 | * 16进制编码工具 7 | * 8 | * @author yuanfeng.z 9 | * @version 1.0 10 | * @date 2019-06-27 11 | */ 12 | public class HexUtil { 13 | 14 | /** 15 | * 16进制大写编码 16 | */ 17 | private static final char[] HEX_CODE_UPPER = "0123456789ABCDEF".toCharArray(); 18 | /** 19 | * 16进制小写编码 20 | */ 21 | private static final char[] HEX_CODE_LOWER = "0123456789abcdef".toCharArray(); 22 | 23 | /** 24 | * 16进制编码 25 | * 26 | * @param plain 编码数据 27 | * @param upper 是否大写 28 | * @return 编码后字符串 29 | */ 30 | public static String hexEncode(byte[] plain, boolean upper) { 31 | Objects.requireNonNull(plain, "plain"); 32 | StringBuilder sb = new StringBuilder(plain.length << 1); 33 | if (upper) { 34 | for (byte b : plain) { 35 | sb.append(HEX_CODE_UPPER[(b >> 4) & 0XF]) 36 | .append(HEX_CODE_UPPER[b & 0XF]); 37 | } 38 | } else { 39 | for (byte b : plain) { 40 | sb.append(HEX_CODE_LOWER[(b >> 4) & 0XF]) 41 | .append(HEX_CODE_LOWER[b & 0XF]); 42 | } 43 | } 44 | return sb.toString(); 45 | } 46 | 47 | /** 48 | * 16进制编码 49 | * 50 | * @param plain 编码数据 51 | * @return 大写16进制编码 52 | */ 53 | public static String hexEncodeUpper(byte[] plain) { 54 | return hexEncode(plain, true); 55 | } 56 | 57 | /** 58 | * 16进制编码 59 | * 60 | * @param plain 编码前数据 61 | * @return 小写16进制编码 62 | */ 63 | public static String hexEncodeLower(byte[] plain) { 64 | return hexEncode(plain, false); 65 | } 66 | 67 | /** 68 | * 16进制解码 69 | * 70 | * @param hex 16进制编码数据 71 | * @return 原始数据 72 | */ 73 | public static byte[] hexDecode(String hex) { 74 | Objects.requireNonNull(hex, "hex"); 75 | int l = hex.length(); 76 | if (1 == hex.length() % 2) { 77 | throw new RuntimeException("the length of hex must be even: " + hex.length()); 78 | } 79 | byte[] bytes = new byte[l / 2]; 80 | for (int i = 0; i < l; i += 2) { 81 | bytes[i / 2] = (byte) ((hex2int(hex.charAt(i)) << 4) + hex2int(hex.charAt(i + 1))); 82 | } 83 | return bytes; 84 | } 85 | 86 | /** 87 | * 字符串转换为16进制字符串 88 | * 89 | * @param s 90 | * @return 91 | */ 92 | public static String stringToHexString(String s) { 93 | String str = ""; 94 | for (int i = 0; i < s.length(); i++) { 95 | int ch = s.charAt(i); 96 | String s4 = Integer.toHexString(ch); 97 | str = str + s4; 98 | } 99 | return str; 100 | } 101 | 102 | /** 103 | * 16进制字符串转换为字符串 104 | * 105 | * @param s 106 | * @return 107 | */ 108 | public static String hexStringToString(String s) { 109 | if (s == null || s.equals("")) { 110 | return null; 111 | } 112 | s = s.replace(" ", ""); 113 | byte[] baKeyword = new byte[s.length() / 2]; 114 | for (int i = 0; i < baKeyword.length; i++) { 115 | try { 116 | baKeyword[i] = (byte) (0xff & Integer.parseInt( 117 | s.substring(i * 2, i * 2 + 2), 16)); 118 | } catch (Exception e) { 119 | e.printStackTrace(); 120 | } 121 | } 122 | try { 123 | s = new String(baKeyword, "utf-8"); 124 | new String(); 125 | } catch (Exception e1) { 126 | e1.printStackTrace(); 127 | } 128 | return s; 129 | } 130 | 131 | 132 | /** 133 | * 16进制字符转16进制数 134 | * 135 | * @param c 字符 136 | * @return 16进制数 137 | */ 138 | private static int hex2int(char c) { 139 | if ('0' <= c && c <= '9') { 140 | return c - '0'; 141 | } 142 | if ('a' <= c && c <= 'f') { 143 | return c - 'a' + 10; 144 | } 145 | if ('A' <= c && c <= 'F') { 146 | return c - 'A' + 10; 147 | } 148 | return 0; 149 | } 150 | 151 | } 152 | -------------------------------------------------------------------------------- /marketdata/src/main/java/com/zyf/marketdata/http/stock/HuobiProMdExchange.java: -------------------------------------------------------------------------------- 1 | package com.zyf.marketdata.http.stock; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.zyf.baseservice.IMdExchange; 5 | import com.zyf.baseservice.util.huobipro.HuobiProUtil; 6 | import com.zyf.common.model.Depth; 7 | import com.zyf.common.model.Kline; 8 | import com.zyf.common.model.Precision; 9 | import com.zyf.common.model.Ticker; 10 | import com.zyf.common.model.enums.ExchangeEnum; 11 | import com.zyf.common.okhttp.OkHttpV3ClientProxy; 12 | import lombok.extern.slf4j.Slf4j; 13 | 14 | import java.util.List; 15 | import java.util.Map; 16 | 17 | /** 18 | * 火币pro交易所行情实现类 19 | * 20 | * @author yuanfeng.z 21 | * @date 2019/6/25 10:02 22 | */ 23 | @Slf4j 24 | public class HuobiProMdExchange implements IMdExchange { 25 | 26 | /** 27 | * 协议 28 | */ 29 | private static final String PROTOCOL = "https://"; 30 | 31 | /** 32 | * 网站 33 | */ 34 | private static final String SITE = "api.huobi.pro"; 35 | 36 | /** 37 | * url 38 | */ 39 | private static final String URL = PROTOCOL + SITE; 40 | 41 | /** 42 | * 价格、数量精度资源路径 43 | */ 44 | private static final String PRESISION = "/v1/common/symbols"; 45 | 46 | /** 47 | * 交易所名字 48 | */ 49 | private final ExchangeEnum name = ExchangeEnum.HUOBIPRO; 50 | 51 | /** 52 | * ticker资源路径 53 | */ 54 | private static final String TICKER = "/market/detail/merged"; 55 | 56 | /** 57 | * depth资源路径 58 | */ 59 | private static final String DEPTH = "/market/depth"; 60 | 61 | /** 62 | * 单例模式 63 | * 64 | * @return 65 | */ 66 | public static HuobiProMdExchange huobiProMdExchange = new HuobiProMdExchange(); 67 | 68 | public static HuobiProMdExchange getInstance() { 69 | return huobiProMdExchange; 70 | } 71 | 72 | private HuobiProMdExchange() { 73 | super(); 74 | } 75 | 76 | /** 77 | * 获取指定币对市场心跳数据 78 | * 79 | * @param symbol 币对 80 | * @return 81 | */ 82 | @Override 83 | public Ticker getTicker(String symbol) { 84 | // 转换币对格式 85 | symbol = HuobiProUtil.transfSymbol(symbol); 86 | 87 | /*获取ticker数据*/ 88 | StringBuilder sb = new StringBuilder(); 89 | sb.append(URL).append(TICKER).append("?").append("symbol=").append(symbol); 90 | String tickerStr = OkHttpV3ClientProxy.get(sb.toString()); 91 | 92 | /*适配*/ 93 | JSONObject jo = JSONObject.parseObject(tickerStr); 94 | Ticker ticker = HuobiProUtil.parseTicker(jo); 95 | return ticker; 96 | } 97 | 98 | @Override 99 | public List getKline(String symbol, String granularity) { 100 | return null; 101 | } 102 | 103 | /** 104 | * 获取指定币对市场深度数据 105 | * 106 | * @param symbol 币对 107 | * @return 108 | */ 109 | @Override 110 | public Depth getDepth(String symbol) { 111 | // 转换币对格式 112 | symbol = HuobiProUtil.transfSymbol(symbol); 113 | 114 | /*获取depth数据*/ 115 | final int depth = 20; 116 | final String type = "step0"; 117 | StringBuilder sb = new StringBuilder(); 118 | sb.append(URL).append(DEPTH) 119 | .append("?").append("symbol=").append(symbol) 120 | .append("&").append("depth=").append(depth) 121 | .append("&").append("type=").append(type); 122 | String depthStr; 123 | try { 124 | depthStr = OkHttpV3ClientProxy.get(sb.toString()); 125 | } catch (Exception e) { 126 | log.error("获取huobi盘口失败,错误异常:" + e.getMessage()); 127 | return null; 128 | } 129 | /*适配*/ 130 | JSONObject jo = JSONObject.parseObject(depthStr); 131 | return HuobiProUtil.parseDepth(jo); 132 | } 133 | 134 | /** 135 | * 获取币对精度 136 | * 137 | * @return 币对精度列表 138 | */ 139 | @Override 140 | public Map getPrecisions() { 141 | /*获取币种精度数据*/ 142 | StringBuilder sb = new StringBuilder(); 143 | sb.append(URL).append(PRESISION); 144 | String accuracysStr = OkHttpV3ClientProxy.get(sb.toString()); 145 | 146 | /*适配*/ 147 | JSONObject jo = JSONObject.parseObject(accuracysStr); 148 | Map precisions = HuobiProUtil.parsePrecisions(jo); 149 | return precisions; 150 | } 151 | 152 | public static void main(String[] args) { 153 | log.info(HuobiProMdExchange.getInstance().getDepth("bchusdt").toString()); 154 | } 155 | 156 | } 157 | -------------------------------------------------------------------------------- /common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | easy-quant 7 | com.zyf 8 | 1.0-SNAPSHOT 9 | 10 | common 11 | 4.0.0 12 | 1.0-SNAPSHOT 13 | 14 | 15 | UTF-8 16 | 1.8 17 | 18 | 19 | 20 | 21 | 22 | org.apache.httpcomponents 23 | httpclient 24 | 4.5.2 25 | 26 | 27 | 28 | org.projectlombok 29 | lombok 30 | 1.18.8 31 | compile 32 | 33 | 34 | cn.hutool 35 | hutool-all 36 | 4.5.11 37 | compile 38 | 39 | 40 | org.yaml 41 | snakeyaml 42 | 1.24 43 | compile 44 | 45 | 46 | com.alibaba 47 | fastjson 48 | 1.2.58 49 | compile 50 | 51 | 52 | com.esotericsoftware.yamlbeans 53 | yamlbeans 54 | 1.13 55 | compile 56 | 57 | 58 | 59 | com.squareup.retrofit2 60 | retrofit 61 | 2.8.0 62 | 63 | 64 | com.squareup.retrofit2 65 | converter-jackson 66 | 2.8.0 67 | 68 | 69 | 70 | org.ehcache 71 | ehcache 72 | 3.7.1 73 | compile 74 | 75 | 76 | junit 77 | junit 78 | 4.12 79 | test 80 | 81 | 82 | 83 | org.apache.commons 84 | commons-lang3 85 | 3.4 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | io.gsonfire 97 | gson-fire 98 | 1.8.0 99 | 100 | 101 | 102 | com.google.code.gson 103 | gson 104 | 2.8.1 105 | 106 | 107 | 108 | org.ta4j 109 | ta4j-core 110 | 0.13 111 | 112 | 113 | org.ta4j 114 | ta4j-examples 115 | 0.13 116 | 117 | 118 | 119 | 120 | com.tictactec 121 | ta-lib 122 | 0.4.0 123 | 124 | 125 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/crypto/HmacUtil.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.crypto; 2 | 3 | import javax.crypto.Mac; 4 | import javax.crypto.spec.SecretKeySpec; 5 | import java.io.UnsupportedEncodingException; 6 | import java.security.MessageDigest; 7 | import java.security.NoSuchAlgorithmException; 8 | import java.util.Objects; 9 | 10 | /** 11 | * Hmac加密工具 12 | * 13 | * @author yuanfeng.z 14 | * @version 1.0 15 | * @date 2019-06-27 16 | */ 17 | public class HmacUtil { 18 | 19 | /** 20 | * Hmac加密 21 | * 22 | * @param message 23 | * @param key 24 | * @param hmacType 25 | * @return 26 | * @throws Exception 27 | */ 28 | public static byte[] hmac(byte[] message, String key, HmacType hmacType) throws Exception { 29 | Objects.requireNonNull(message, "message"); 30 | SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), hmacType.getName()); 31 | Mac mac = Mac.getInstance(hmacType.getName()); 32 | mac.init(signingKey); 33 | return mac.doFinal(message); 34 | } 35 | 36 | /** 37 | * Hmac加密 38 | * 39 | * @param message 40 | * @param key 41 | * @param hmacType 42 | * @param upper 是否大写 43 | * @return 44 | */ 45 | private static String hmac(byte[] message, String key, HmacType hmacType, boolean upper) { 46 | try { 47 | byte[] bytes = hmac(message, key, hmacType); 48 | return HexUtil.hexEncode(bytes, upper); 49 | } catch (Exception e) { 50 | e.printStackTrace(); 51 | } 52 | return null; 53 | } 54 | 55 | public static String HmacMD5(String message, String key) { 56 | return hmac(message.getBytes(), key, HmacType.HMAC_MD5, true); 57 | } 58 | 59 | public static String HmacSHA1(String message, String key) { 60 | return hmac(message.getBytes(), key, HmacType.HMAC_SHA1, true); 61 | } 62 | 63 | public static String HmacSHA256(String message, String key) { 64 | return hmac(message.getBytes(), key, HmacType.HMAC_SHA256, true); 65 | } 66 | 67 | public static String HmacSHA384(String message, String key) { 68 | return hmac(message.getBytes(), key, HmacType.HMAC_SHA384, true); 69 | } 70 | 71 | public static String HmacSHA512(String message, String key) { 72 | return hmac(message.getBytes(), key, HmacType.HMAC_SHA512, true); 73 | } 74 | 75 | public static String hmacMD5(String message, String key) { 76 | return hmac(message.getBytes(), key, HmacType.HMAC_MD5, false); 77 | } 78 | 79 | public static String hmacSHA1(String message, String key) { 80 | return hmac(message.getBytes(), key, HmacType.HMAC_SHA1, false); 81 | } 82 | 83 | public static String hmacSHA256(String message, String key) { 84 | return hmac(message.getBytes(), key, HmacType.HMAC_SHA256, false); 85 | } 86 | 87 | public static String hmacSHA384(String message, String key) { 88 | return hmac(message.getBytes(), key, HmacType.HMAC_SHA384, false); 89 | } 90 | 91 | public static String hmacSHA512(String message, String key) { 92 | return hmac(message.getBytes(), key, HmacType.HMAC_SHA512, false); 93 | } 94 | 95 | /** 96 |     * 利用java原生的类实现SHA256加密 97 |     * @param str 加密后的报文 98 |     * @return 99 |     */ 100 | public static String getSHA256(String str) { 101 | MessageDigest messageDigest; 102 | String encodestr = ""; 103 | try { 104 | messageDigest = MessageDigest.getInstance("SHA-256"); 105 | messageDigest.update(str.getBytes("UTF-8")); 106 | encodestr = byte2Hex(messageDigest.digest()); 107 | } catch (NoSuchAlgorithmException e) { 108 | e.printStackTrace(); 109 | } catch (UnsupportedEncodingException e) { 110 | e.printStackTrace(); 111 | } 112 | return encodestr; 113 | } 114 | 115 | /** 116 |     * 将byte转为16进制 117 |     * @param bytes 118 |     * @return 119 |     */ 120 | private static String byte2Hex(byte[] bytes) { 121 | StringBuffer stringBuffer = new StringBuffer(); 122 | String temp = null; 123 | for (int i = 0; i < bytes.length; i++) { 124 | temp = Integer.toHexString(bytes[i] & 0xFF); 125 | if (temp.length() == 1) { 126 | //1得到一位的进行补0操作 127 | stringBuffer.append("0"); 128 | } 129 | stringBuffer.append(temp); 130 | } 131 | return stringBuffer.toString(); 132 | } 133 | 134 | } 135 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/util/YamlUtil.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.util; 2 | 3 | import com.esotericsoftware.yamlbeans.YamlConfig; 4 | import com.esotericsoftware.yamlbeans.YamlException; 5 | import com.esotericsoftware.yamlbeans.YamlReader; 6 | import com.esotericsoftware.yamlbeans.YamlWriter; 7 | import org.yaml.snakeyaml.DumperOptions; 8 | import org.yaml.snakeyaml.Yaml; 9 | import org.yaml.snakeyaml.reader.UnicodeReader; 10 | 11 | import java.io.*; 12 | import java.util.LinkedHashMap; 13 | import java.util.Map; 14 | 15 | /** 16 | * YML文件工具类 17 | * 18 | * @author yuanfeng.z 19 | * @date 2019-07-12 20 | */ 21 | public class YamlUtil { 22 | 23 | /** 24 | * 获取YAML接口 25 | * 26 | * @return 27 | */ 28 | private static Yaml getYaml() { 29 | DumperOptions options = new DumperOptions(); 30 | // 设置读取方式 31 | options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); 32 | return new Yaml(options); 33 | } 34 | 35 | /** 36 | * 读取Yaml文件 37 | * 38 | * @param src YAML文件 39 | * @return 40 | * @throws IOException 41 | */ 42 | public static Map read(File src) throws IOException { 43 | Map result = new LinkedHashMap<>(); 44 | FileInputStream inputStream = null; 45 | UnicodeReader reader = null; 46 | try { 47 | inputStream = new FileInputStream(src); 48 | reader = new UnicodeReader(inputStream); 49 | LinkedHashMap dataMap = getYaml().load(reader); 50 | if (dataMap != null) { 51 | return dataMap; 52 | } 53 | } finally { 54 | if (reader != null) { 55 | reader.close(); 56 | } 57 | if (inputStream != null) { 58 | inputStream.close(); 59 | } 60 | } 61 | return result; 62 | } 63 | 64 | /** 65 | * 写入Yaml文件 66 | * 67 | * @param dest YAML文件 68 | * @param key 键 69 | * @param value 值 70 | * @throws IOException 71 | */ 72 | public static void write(File dest, String key, Object value) throws IOException { 73 | FileInputStream inputStream = null; 74 | UnicodeReader reader = null; 75 | try { 76 | inputStream = new FileInputStream(dest); 77 | reader = new UnicodeReader(inputStream); 78 | Yaml yaml = getYaml(); 79 | LinkedHashMap dataMap = yaml.load(reader); 80 | if (null == dataMap) { 81 | dataMap = new LinkedHashMap<>(); 82 | } 83 | dataMap.put(key, value); 84 | yaml.dump(dataMap, new FileWriter(dest)); 85 | } finally { 86 | if (reader != null) { 87 | reader.close(); 88 | } 89 | if (inputStream != null) { 90 | inputStream.close(); 91 | } 92 | } 93 | } 94 | 95 | /** 96 | * 反序列化Bean 97 | * 98 | * @param file YAML文件 99 | * @param clazz 类型 100 | * @param 101 | * @return 102 | * @throws FileNotFoundException, YamlException 103 | */ 104 | public static T yamlToBean(File file, Class clazz) throws FileNotFoundException, YamlException { 105 | YamlReader reader = new YamlReader(new FileReader(file)); 106 | return reader.read(clazz); 107 | } 108 | 109 | /** 110 | * 反序列化Bean 111 | * 112 | * @param file YAML文件 113 | * @param clazz 类型 114 | * @param config 反序列化配置 115 | * @param 116 | * @return 117 | * @throws FileNotFoundException, YamlException 118 | */ 119 | public static T yamlToBean(File file, Class clazz, YamlConfig config) throws FileNotFoundException, YamlException { 120 | YamlReader reader = new YamlReader(new FileReader(file), config); 121 | return reader.read(clazz); 122 | } 123 | 124 | 125 | /** 126 | * 序列化Bean 127 | * 128 | * @param file YAML文件 129 | * @param bean 序列化对象 130 | * @throws Exception 131 | */ 132 | public static void beanToYaml(File file, Object bean) throws IOException { 133 | YamlWriter writer = new YamlWriter(new FileWriter(file)); 134 | writer.write(bean); 135 | writer.close(); 136 | } 137 | 138 | /** 139 | * 序列化Bean 140 | * 141 | * @param file YAML文件 142 | * @param bean 序列化对象 143 | * @param config 序列化配置 144 | * @throws IOException 145 | */ 146 | public static void beanToYaml(File file, Object bean, YamlConfig config) throws IOException { 147 | YamlWriter writer = new YamlWriter(new FileWriter(file), config); 148 | writer.write(bean); 149 | writer.close(); 150 | } 151 | 152 | } 153 | -------------------------------------------------------------------------------- /marketdata/src/main/java/com/zyf/marketdata/http/option/HuobiProMdOptionExchange.java: -------------------------------------------------------------------------------- 1 | package com.zyf.marketdata.http.option; 2 | 3 | import com.alibaba.fastjson.JSONObject; 4 | import com.zyf.baseservice.IMdExchange; 5 | import com.zyf.baseservice.util.huobipro.HuobiProFutUtil; 6 | import com.zyf.baseservice.util.huobipro.HuobiProOptionUtil; 7 | import com.zyf.common.model.Depth; 8 | import com.zyf.common.model.Kline; 9 | import com.zyf.common.model.Precision; 10 | import com.zyf.common.model.Ticker; 11 | import com.zyf.common.model.option.Instrument; 12 | import com.zyf.common.model.option.OptionDetailInfo; 13 | import com.zyf.common.okhttp.OkHttpV3ClientProxy; 14 | import lombok.extern.slf4j.Slf4j; 15 | 16 | import java.util.List; 17 | import java.util.Map; 18 | 19 | /** 20 | * 火币期权行情类 21 | * 22 | * @author yuanfeng.z 23 | * @date q 20:54 24 | */ 25 | @Slf4j 26 | public class HuobiProMdOptionExchange implements IMdExchange { 27 | 28 | /** 29 | * 协议 30 | */ 31 | private static final String PROTOCOL = "https://"; 32 | 33 | /** 34 | * 网站 35 | */ 36 | private static final String SITE = "api.hbdm.com"; 37 | 38 | /** 39 | * url 40 | */ 41 | private static final String URL = PROTOCOL + SITE; 42 | 43 | /** 44 | * 期权合约 45 | */ 46 | private static final String OPTION_CONTRACT = "/option-api/v1/option_contract_info"; 47 | 48 | /** 49 | * depth资源路径 50 | */ 51 | private static final String DEPTH = "/option-ex/market/depth"; 52 | 53 | /** 54 | * 查询合约市场指标 (包含iv) 55 | */ 56 | private static final String MARKET_INDEX = "/option-api/v1/option_market_index"; 57 | 58 | 59 | @Override 60 | public Ticker getTicker(String symbol) { 61 | return null; 62 | } 63 | 64 | @Override 65 | public List getKline(String symbol, String granularity) { 66 | return null; 67 | } 68 | 69 | @Override 70 | public Depth getDepth(String symbol) { 71 | // 转换币对格式 72 | symbol = HuobiProFutUtil.transfSymbol(symbol); 73 | 74 | /*获取depth数据*/ 75 | final String type = "step0"; 76 | StringBuilder sb = new StringBuilder(); 77 | sb.append(URL).append(DEPTH) 78 | .append("?").append("contract_code=").append(symbol) 79 | .append("&").append("type=").append(type); 80 | String depthStr; 81 | try { 82 | depthStr = OkHttpV3ClientProxy.get(sb.toString()); 83 | } catch (Exception e) { 84 | log.error("获取huobi盘口失败,错误异常:" + e.getMessage()); 85 | return null; 86 | } 87 | /*适配*/ 88 | JSONObject jo = JSONObject.parseObject(depthStr); 89 | return HuobiProFutUtil.parseDepth(jo); 90 | } 91 | 92 | @Override 93 | public Map getPrecisions() { 94 | return null; 95 | } 96 | 97 | /** 98 | * 查询合约市场指标 (包含iv) 99 | * @return 100 | */ 101 | public static List getOptionDetailInfo(String instrumentName) { 102 | /*获取symbol数据*/ 103 | StringBuilder sb = new StringBuilder(); 104 | sb.append(URL).append(MARKET_INDEX). 105 | append("?").append("contract_code="). 106 | append(instrumentName); 107 | String depthStr; 108 | try { 109 | depthStr = OkHttpV3ClientProxy.get(sb.toString()); 110 | } catch (Exception e) { 111 | log.error("获取huobi合约市场指标名失败,错误异常:" + e.getMessage()); 112 | return null; 113 | } 114 | /*适配*/ 115 | JSONObject jo = JSONObject.parseObject(depthStr); 116 | return HuobiProOptionUtil.parseOptionDetailInfo(jo); 117 | } 118 | 119 | /** 120 | * 获取合约信息 121 | * @return 122 | */ 123 | public static List getContractInfo() { 124 | /*获取symbol数据*/ 125 | StringBuilder sb = new StringBuilder(); 126 | sb.append(URL).append(OPTION_CONTRACT); 127 | String depthStr; 128 | try { 129 | depthStr = OkHttpV3ClientProxy.get(sb.toString()); 130 | } catch (Exception e) { 131 | log.error("获取huobi期权合约名失败,错误异常:" + e.getMessage()); 132 | return null; 133 | } 134 | /*适配*/ 135 | JSONObject jo = JSONObject.parseObject(depthStr); 136 | return HuobiProOptionUtil.parseContractInfo(jo); 137 | } 138 | 139 | 140 | public static void main(String[] args) { 141 | List instruments = HuobiProMdOptionExchange.getContractInfo(); 142 | HuobiProMdOptionExchange ex = new HuobiProMdOptionExchange(); 143 | for (Instrument i : instruments) { 144 | Depth df = ex.getDepth(i.getName()); 145 | log.info(HuobiProMdOptionExchange.getOptionDetailInfo(i.getName()).toString()); 146 | // log.info(ex.getDepth(i.getName()).toString()); 147 | } 148 | 149 | log.info(instruments.toString()); 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/util/DateUtil.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.util; 2 | 3 | import java.text.ParseException; 4 | import java.text.SimpleDateFormat; 5 | import java.time.Instant; 6 | import java.time.LocalDate; 7 | import java.time.LocalDateTime; 8 | import java.time.ZoneId; 9 | import java.util.Date; 10 | 11 | /** 12 | * @author yuanfeng.z 13 | * @description 时间操作类 14 | * @date 2019/2/21 18:46 15 | */ 16 | public class DateUtil { 17 | /** 18 | * 天(毫秒) 19 | */ 20 | public static Double MS_DAY = 86400000d; 21 | 22 | /** 23 | * 时间格式 24 | */ 25 | public static String yyyyMMddHHmmss = "yyyy-MM-dd HH:mm:ss"; 26 | 27 | /** 28 | * 时间格式 29 | */ 30 | public static String yyyyMMddTHHmmssSSSZ = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; 31 | 32 | /** 33 | * 时间格式 34 | */ 35 | public static String yyyyMMddHHmmssSSS = "yyyy-MM-dd HH:mm:ss:SSS"; 36 | 37 | /** 38 | * 时间格式 39 | */ 40 | public static String yyyyMMdd = "yyyyMMdd"; 41 | 42 | /** 43 | * 时间间隔时间戳 44 | * 45 | * @param begin 开始时间 46 | * @param end 结束时间 47 | * @return 48 | */ 49 | public static Double timeInterval(Date begin, Date end) { 50 | return ((end.getTime() - begin.getTime()) / MS_DAY); 51 | } 52 | 53 | /** 54 | * java.util.Date --> java.time.LocalDateTime 55 | * 56 | * @param date 57 | * @return 58 | */ 59 | public static LocalDateTime dateToLocalDateTime(Date date) { 60 | Instant instant = date.toInstant(); 61 | ZoneId zone = ZoneId.systemDefault(); 62 | LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone); 63 | return localDateTime; 64 | } 65 | 66 | /** 67 | * java.util.Date --> java.time.LocalDate 68 | * 69 | * @param date 70 | * @return 71 | */ 72 | public static LocalDate dateToLocalDate(Date date) { 73 | Instant instant = date.toInstant(); 74 | ZoneId zoneId = ZoneId.systemDefault(); 75 | LocalDate localDate = instant.atZone(zoneId).toLocalDate(); 76 | return localDate; 77 | } 78 | 79 | /** 80 | * string to date 81 | * 82 | * @param str 83 | * @return 84 | */ 85 | public static Date str2Date(String str) { 86 | Date date; 87 | try { 88 | SimpleDateFormat sdf = new SimpleDateFormat(yyyyMMddHHmmssSSS); 89 | date = sdf.parse(str); 90 | } catch (ParseException e) { 91 | System.out.println(e.getMessage()); 92 | return null; 93 | } 94 | return date; 95 | } 96 | 97 | /** 98 | * string to date 99 | * 100 | * @param str 101 | * @return 102 | */ 103 | public static Date str2Date(String str, String format) { 104 | Date date; 105 | try { 106 | SimpleDateFormat sdf = new SimpleDateFormat(format); 107 | date = sdf.parse(str); 108 | } catch (ParseException e) { 109 | System.out.println(e.getMessage()); 110 | return null; 111 | } 112 | return date; 113 | } 114 | 115 | /** 116 | * string to timestamp 117 | * 118 | * @param str 119 | * @return 120 | */ 121 | public static Long str2TimeStamp(String str) { 122 | return DateUtil.str2Date(str).getTime(); 123 | } 124 | 125 | /** 126 | * string to timestamp 127 | * 128 | * @param str 129 | * @param format 130 | * @return 131 | */ 132 | public static Long str2TimeStamp(String str, String format) { 133 | return DateUtil.str2Date(str, format).getTime(); 134 | } 135 | 136 | /** 137 | * timestamp to date 138 | * 139 | * @param time 时间戳 140 | * @return 141 | */ 142 | public static Date timestamp2Date(long time) { 143 | Date date; 144 | try { 145 | SimpleDateFormat sdf = new SimpleDateFormat(yyyyMMddHHmmssSSS); 146 | String str = sdf.format(time); 147 | date = sdf.parse(str); 148 | } catch (ParseException e) { 149 | System.out.println(e.getMessage()); 150 | return null; 151 | } 152 | return date; 153 | } 154 | 155 | /** 156 | * timestamp to string 157 | * 158 | * @param time 时间戳 159 | * @return 160 | */ 161 | public static String timestamp2Str(long time) { 162 | SimpleDateFormat sdf = new SimpleDateFormat(yyyyMMddHHmmssSSS); 163 | String str = sdf.format(time); 164 | return str; 165 | } 166 | 167 | /** 168 | * 获取时间的例子 169 | */ 170 | public static void example() { 171 | LocalDateTime localDateTime = LocalDateTime.now(); 172 | // 获取年 173 | localDateTime.getYear(); 174 | // 获取月份 175 | localDateTime.getMonth(); 176 | // 获取周里的第几天 177 | localDateTime.getDayOfWeek(); 178 | // 获取月里面的第几天 179 | localDateTime.getDayOfMonth(); 180 | // 获取年里面的第几天 181 | localDateTime.getDayOfYear(); 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/util/BigDecimalUtil.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.util; 2 | 3 | import java.math.BigDecimal; 4 | import java.util.Arrays; 5 | 6 | /** 7 | * BigDecimal工具类 8 | */ 9 | public class BigDecimalUtil { 10 | public static BigDecimal add(BigDecimal a, BigDecimal b) { 11 | return a.add(b); 12 | } 13 | public static BigDecimal add(BigDecimal... a) { 14 | if (null != a) { 15 | if (0 == a.length) { return null; } 16 | BigDecimal r = a[0]; 17 | for (int i = 1; i < a.length; i++) { r = add(r, a[i]); } 18 | return r; 19 | } 20 | return null; 21 | } 22 | 23 | /** 24 | * 减法 25 | * @param a 26 | * @param b 27 | * @return 28 | */ 29 | public static BigDecimal sub(BigDecimal a, BigDecimal b) { 30 | return a.subtract(b); 31 | } 32 | public static BigDecimal sub(BigDecimal... a) { 33 | if (null != a) { 34 | if (0 == a.length) { return null; } 35 | BigDecimal r = a[0]; 36 | for (int i = 1; i < a.length; i++) { r = sub(r, a[i]); } 37 | return r; 38 | } 39 | return null; 40 | } 41 | 42 | public static BigDecimal mul(BigDecimal a, BigDecimal b) { 43 | return a.multiply(b); 44 | } 45 | public static BigDecimal div(BigDecimal a, BigDecimal b) { 46 | return div(a, b, 8); 47 | } 48 | public static BigDecimal div(BigDecimal a, BigDecimal b, int scale) { 49 | return a.divide(b, scale, BigDecimal.ROUND_DOWN); 50 | } 51 | private static BigDecimal NEG = new BigDecimal("-1"); 52 | public static BigDecimal neg(BigDecimal a) { 53 | return NEG.multiply(a); 54 | } 55 | 56 | private static Boolean exist(BigDecimal a, BigDecimal b) { 57 | if (null != a) { 58 | if (null != b) { 59 | return null; 60 | } else { 61 | return false; 62 | } 63 | } else { 64 | if (null != b) { 65 | return null; 66 | } else { 67 | return true; 68 | } 69 | } 70 | } 71 | 72 | public static boolean equal(BigDecimal a, BigDecimal b) { 73 | Boolean result = exist(a, b); 74 | return null != result ? result : 0 == a.compareTo(b); 75 | } 76 | public static boolean less(BigDecimal a, BigDecimal b) { 77 | Boolean result = exist(a, b); 78 | return null != result ? result : a.compareTo(b) < 0; 79 | } 80 | public static boolean lessOrEqual(BigDecimal a, BigDecimal b) { 81 | Boolean result = exist(a, b); 82 | return null != result ? result : a.compareTo(b) <= 0; 83 | } 84 | public static boolean greater(BigDecimal a, BigDecimal b) { 85 | Boolean result = exist(a, b); 86 | return null != result ? result : 0 < a.compareTo(b); 87 | } 88 | public static boolean greaterOrEqual(BigDecimal a, BigDecimal b) { 89 | Boolean result = exist(a, b); 90 | return null != result ? result : 0 <= a.compareTo(b); 91 | } 92 | 93 | public static BigDecimal avg(BigDecimal... num) { 94 | BigDecimal count = new BigDecimal(num.length); 95 | return div(Arrays.stream(num).reduce(BigDecimal.ZERO, BigDecimal::add), count, 16); 96 | } 97 | 98 | public static BigDecimal max(BigDecimal... num) { 99 | return Arrays.stream(num).max(BigDecimal::compareTo).get(); 100 | } 101 | 102 | public static BigDecimal min(BigDecimal... num) { 103 | return Arrays.stream(num).min(BigDecimal::compareTo).get(); 104 | } 105 | 106 | /** 107 | * 求余 108 | * @param dividend 被除数 109 | * @param divisor 除数 110 | * @return BigDecimal[0]:商 BigDecimal[1]:余 111 | */ 112 | public static BigDecimal[] divideAndRemainder(BigDecimal dividend, BigDecimal divisor) { 113 | if (divisor == null || BigDecimal.ZERO.equals(divisor)) { 114 | return new BigDecimal[2]; 115 | } 116 | return dividend.divideAndRemainder(divisor); 117 | } 118 | 119 | public static BigDecimal usdUp(BigDecimal usd) { 120 | return usd.setScale(2, BigDecimal.ROUND_UP); 121 | } 122 | 123 | public static BigDecimal usdDown(BigDecimal usd) { 124 | return usd.setScale(2, BigDecimal.ROUND_DOWN); 125 | } 126 | 127 | public static BigDecimal btcUp(BigDecimal btc) { 128 | return btc.setScale(8, BigDecimal.ROUND_UP); 129 | } 130 | 131 | public static BigDecimal btcDown(BigDecimal btc) { 132 | return btc.setScale(8, BigDecimal.ROUND_DOWN); 133 | } 134 | 135 | /** 136 | *

137 | * 判断正负,正数直接返回,负数转正数返回 138 | *

139 | * */ 140 | public static BigDecimal positive_number(BigDecimal decimal){ 141 | int i=decimal.compareTo(BigDecimal.ZERO); 142 | if (i>=0){ 143 | return decimal; 144 | } 145 | return decimal.negate(); 146 | } 147 | 148 | /** 149 | *

150 | * 判断正负,正数返true,负数返false 151 | *

152 | * */ 153 | public static Boolean plus_or_minus(BigDecimal decimal){ 154 | return decimal.compareTo(BigDecimal.ZERO)>= 0; 155 | } 156 | 157 | } 158 | 159 | -------------------------------------------------------------------------------- /trade/src/main/java/com/zyf/trade/proxy/TradeExchangeProxy.java: -------------------------------------------------------------------------------- 1 | package com.zyf.trade.proxy; 2 | 3 | import com.zyf.baseservice.ITradeExchange; 4 | import com.zyf.common.model.*; 5 | import com.zyf.common.model.enums.ExchangeEnum; 6 | import com.zyf.common.model.enums.SecuritiesTypeEnum; 7 | import com.zyf.common.util.CommomUtil; 8 | import com.zyf.trade.factory.TradeExchangeFactory; 9 | import lombok.EqualsAndHashCode; 10 | import lombok.Getter; 11 | import lombok.ToString; 12 | 13 | import java.math.BigDecimal; 14 | import java.util.List; 15 | import java.util.Map; 16 | 17 | /** 18 | * 交易代理类(统一异常处理) 19 | * @author yuanfeng.z 20 | * @date 2019/7/4 11:26 21 | */ 22 | @Getter 23 | @ToString 24 | @EqualsAndHashCode 25 | public class TradeExchangeProxy { 26 | /** 27 | * 交易交易所对象 28 | */ 29 | private ITradeExchange tradeExchange; 30 | 31 | /** 32 | * 交易所名称 33 | */ 34 | private ExchangeEnum exchangeNameEnum; 35 | 36 | /** 37 | * 交易所名称 38 | */ 39 | private String exchangeName; 40 | 41 | /** 42 | * 所有币种精度 43 | */ 44 | Map precisionMap; 45 | 46 | public TradeExchangeProxy(ExchangeEnum exchangeName, SecuritiesTypeEnum type, String accessKey, String secretKey) { 47 | this.tradeExchange = TradeExchangeFactory.createTradeExchange(exchangeName, type, accessKey, secretKey); 48 | this.exchangeNameEnum = exchangeName; 49 | this.exchangeName = exchangeName.getValue(); 50 | } 51 | 52 | public TradeExchangeProxy(String exchangeName, String type, String accessKey, String secretKey) { 53 | this(CommomUtil.toExchangeEnum(exchangeName), CommomUtil.toSecuritiesTypeEnum(type), accessKey, secretKey); 54 | } 55 | 56 | public ITradeExchange getE() { 57 | return this.tradeExchange; 58 | } 59 | 60 | /** 61 | * 获取账户信息 62 | * @param symbol 63 | * @return 64 | */ 65 | public Account getAccount(String symbol) { 66 | Account account = this.tradeExchange.getAccount(symbol); 67 | return account; 68 | } 69 | 70 | /** 71 | * 市价买入 72 | * @param symbol 币对 73 | * @param cost 费用 74 | * @return 订单id 75 | */ 76 | public String buyMarket(String symbol, BigDecimal cost) { 77 | String id = this.tradeExchange.buyMarket(symbol, cost); 78 | return id; 79 | } 80 | 81 | /** 82 | * 市价卖出 83 | * @param symbol 币对 84 | * @param quantity 卖出数量 85 | * @return 订单id 86 | */ 87 | public String sellMarket(String symbol, BigDecimal quantity) { 88 | String id = this.tradeExchange.sellMarket(symbol, quantity); 89 | return id; 90 | } 91 | 92 | /** 93 | * 限价买入 94 | * @param symbol 币对 95 | * @param price 价格 96 | * @param quanatity 价格 97 | * @return 订单id 98 | */ 99 | public String buyLimit(String symbol, BigDecimal price, BigDecimal quanatity) { 100 | String id = this.tradeExchange.buyLimit(symbol, price, quanatity); 101 | return id; 102 | } 103 | 104 | /** 105 | * 限价卖出 106 | * @param symbol 币对 107 | * @param price 价格 108 | * @param quanatity 价格 109 | * @return 订单id 110 | */ 111 | public String sellLimit(String symbol, BigDecimal price, BigDecimal quanatity) { 112 | String id = this.tradeExchange.sellLimit(symbol, price, quanatity); 113 | return id; 114 | } 115 | 116 | 117 | /** 118 | * 根据订单id撤单 119 | * @param symbol 币对 120 | * @param orderId 订单id 121 | * @return 122 | */ 123 | public Boolean cancelOrder(String symbol, String orderId) { 124 | Boolean b = this.tradeExchange.cancelOrder(symbol, orderId); 125 | return b; 126 | } 127 | 128 | /** 129 | * 批量撤单 130 | * @param symbol 币对 131 | * @param ids 132 | * @return 133 | */ 134 | public Boolean cancelOrders(String symbol, List ids) { 135 | Boolean b = this.tradeExchange.cancelOrders(symbol, ids); 136 | return b; 137 | } 138 | 139 | /** 140 | * 获取所有的订单 141 | * @param symbol 币对 142 | * @return 订单列表 143 | */ 144 | public List getOrders(String symbol) { 145 | List orders = this.tradeExchange.getOrders(symbol); 146 | return orders; 147 | } 148 | 149 | /** 150 | * 获取指定id的订单信息 151 | * @param symbol 币对 152 | * @param orderId 订单id 153 | * @return 订单 154 | */ 155 | public Order getOrder(String symbol, String orderId) { 156 | Order orders = this.tradeExchange.getOrder(symbol, orderId); 157 | return orders; 158 | } 159 | 160 | /** 161 | * 获取成交明细 162 | * @param symbol 163 | * @param orderId 164 | * @return 165 | */ 166 | public List getTrade(String symbol, String orderId) { 167 | List trades = this.tradeExchange.getTrades(symbol, orderId); 168 | return trades; 169 | } 170 | 171 | /** 172 | * 获取挂单 173 | * @param symbol 174 | * @return 175 | */ 176 | public List getPendingOrders(String symbol) { 177 | List pendingOrders = this.tradeExchange.getPendingOrders(symbol); 178 | return pendingOrders; 179 | } 180 | 181 | /** 182 | * 获取所有持仓 183 | * @param symbol 184 | * @return 185 | */ 186 | public List getPosition(String symbol) { 187 | List positions = this.tradeExchange.getPositions(symbol); 188 | return positions; 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /common/src/main/java/com/zyf/common/model/future/BitMEXInstrument.java: -------------------------------------------------------------------------------- 1 | package com.zyf.common.model.future; 2 | 3 | import lombok.Data; 4 | 5 | import java.math.BigDecimal; 6 | import java.util.Date; 7 | 8 | @Data 9 | public class BitMEXInstrument { 10 | private String symbol; // "XBTZ14", 11 | private String rootSymbol; // "XBT", 12 | private String state; // "Settled", 13 | private String typ; // "FXXXS", 14 | private Date listing; // "2014-11-21T20; //00; //00.000Z", 15 | private Date front; // "2014-11-28T12; //00; //00.000Z", 16 | private Date expiry; // "2014-12-26T12; //00; //00.000Z", 17 | private Date settle; // "2014-12-26T12; //00; //00.000Z", 18 | private String relistInterval; // null, 19 | private String inverseLeg; // "", 20 | private String sellLeg; // "", 21 | private String buyLeg; // "", 22 | private String optionStrikePcnt; // null, 23 | private String optionStrikeRound; // null, 24 | private String optionStrikePrice; // null, 25 | private String optionMultiplier; // null, 26 | private String positionCurrency; // "", 27 | private String underlying; // "XBT", 28 | private String quoteCurrency; // "USD", 29 | private String underlyingSymbol; // "XBT=", 30 | private String reference; // "BMEX", 31 | private String referenceSymbol; // ".XBT2H", 32 | private String calcInterval; // null, 33 | private String publishInterval; // null, 34 | private String publishTime; // null, 35 | private BigDecimal maxOrderQty; // 10000000, 36 | private BigDecimal maxPrice; // 1000000, 37 | private Integer lotSize; // 1, 38 | private BigDecimal tickSize; // 0.01, 39 | private BigDecimal multiplier; // 1000, 40 | private String settlCurrency; // "XBt", 41 | private BigDecimal underlyingToPositionMultiplier; // null, 42 | private BigDecimal underlyingToSettleMultiplier; // 100000000, 43 | private BigDecimal quoteToSettleMultiplier; // null, 44 | private Boolean isQuanto; // true, 45 | private Boolean isInverse; // false, 46 | private BigDecimal initMargin; // 0.3, 47 | private BigDecimal maintMargin; // 0.2, 48 | private BigDecimal riskLimit; // 25000000000, 49 | private BigDecimal riskStep; // 5000000000, 50 | private BigDecimal limit; // 0.2, 51 | private Boolean capped; // false, 52 | private Boolean taxed; // false, 53 | private Boolean deleverage; // false, 54 | private BigDecimal makerFee; // 0.00005, 55 | private BigDecimal takerFee; // 0.00005, 56 | private BigDecimal settlementFee; // 0.00005, 57 | private BigDecimal insuranceFee; // 0.00015, 58 | private String fundingBaseSymbol; // "", 59 | private String fundingQuoteSymbol; // "", 60 | private String fundingPremiumSymbol; // "", 61 | private Date fundingTimestamp; // null, 62 | private Long fundingInterval; // null, 63 | private BigDecimal fundingRate; // null, 64 | private BigDecimal indicativeFundingRate; // null, 65 | private Long rebalanceTimestamp; // null, 66 | private BigDecimal rebalanceInterval; // null, 67 | private Date openingTimestamp; // "2014-12-26T12; //00; //00.000Z", 68 | private Date closingTimestamp; // "2014-12-26T12; //00; //00.000Z", 69 | private Date sessionInterval; // "2000-01-01T08; //00; //00.000Z", 70 | private BigDecimal prevClosePrice; // 319, 71 | private BigDecimal limitDownPrice; // 255.2, 72 | private BigDecimal limitUpPrice; // 382.8, 73 | private BigDecimal bankruptLimitDownPrice; // null, 74 | private BigDecimal bankruptLimitUpPrice; // null, 75 | private BigDecimal prevTotalVolume; // 323564, 76 | private BigDecimal totalVolume; // 348271, 77 | private BigDecimal volume; // 0, 78 | private BigDecimal volume24h; // 0, 79 | private BigDecimal prevTotalTurnover; // 0, 80 | private BigDecimal totalTurnover; // 0, 81 | private BigDecimal turnover; // 0, 82 | private BigDecimal turnover24h; // 0, 83 | private BigDecimal prevPrice24h; // 323.33, 84 | private String vwap; // null, 85 | private BigDecimal highPrice; // null, 86 | private BigDecimal lowPrice; // null, 87 | private BigDecimal lastPrice; // 323.33, 88 | private BigDecimal lastPriceProtected; // 323.33, 89 | private String lastTickDirection; // "PlusTick", 90 | private BigDecimal lastChangePcnt; // 0, 91 | private BigDecimal bidPrice; // null, 92 | private BigDecimal midPrice; // null, 93 | private BigDecimal askPrice; // null, 94 | private BigDecimal impactBidPrice; // null, 95 | private BigDecimal impactMidPrice; // null, 96 | private BigDecimal impactAskPrice; // null, 97 | private Boolean hasLiquidity; // false, 98 | private BigDecimal openInterest; // 0, 99 | private BigDecimal openValue; // 0, 100 | private String fairMethod; // "", 101 | private BigDecimal fairBasisRate; // null, 102 | private BigDecimal fairBasis; // 0, 103 | private BigDecimal fairPrice; // 323.33, 104 | private String markMethod; // "LastPrice", 105 | private BigDecimal markPrice; // 323.33, 106 | private BigDecimal indicativeTaxRate; // null, 107 | private BigDecimal indicativeSettlePrice; // 323.33, 108 | private BigDecimal optionUnderlyingPrice; // null, 109 | private BigDecimal settledPrice; // 323.33, 110 | private Date timestamp; // "2014-11-21T21; //00; //02.409Z" 111 | } 112 | -------------------------------------------------------------------------------- /baseservice/src/main/java/com/zyf/baseservice/util/okex/OkexSignUtil.java: -------------------------------------------------------------------------------- 1 | package com.zyf.baseservice.util.okex; 2 | 3 | import okhttp3.OkHttpClient; 4 | import okhttp3.Request; 5 | import okhttp3.Response; 6 | 7 | import javax.crypto.Mac; 8 | import javax.crypto.spec.SecretKeySpec; 9 | import java.io.IOException; 10 | import java.io.UnsupportedEncodingException; 11 | import java.net.URLDecoder; 12 | import java.net.URLEncoder; 13 | import java.security.InvalidKeyException; 14 | import java.security.NoSuchAlgorithmException; 15 | import java.text.SimpleDateFormat; 16 | import java.util.*; 17 | 18 | /** 19 | * okex签名加密工具类 20 | * @author yuanfeng.z 21 | * @date 2019/6/28 9:30 22 | */ 23 | public class OkexSignUtil { 24 | 25 | /** 26 | * 字符编码 27 | */ 28 | public final static String INPUT_CHARSET = "UTF-8"; 29 | /** 30 | * 加密方法 31 | */ 32 | private static final String SIGNATURE_METHOD = "HmacSHA256"; 33 | /** 34 | * 超时时间 35 | */ 36 | private final static int TIME_OUT = 30 * 60 * 1000; 37 | 38 | 39 | /** 40 | * url编码 41 | * 42 | * @param content 43 | * @param charset 44 | * @return 45 | */ 46 | public static String urlEncoded(String content, String charset) { 47 | try { 48 | return URLEncoder.encode(content, charset); 49 | } catch (UnsupportedEncodingException e) { 50 | throw new RuntimeException("指定的编码集不对,您目前指定的编码集是:" + charset); 51 | } 52 | } 53 | 54 | public static String urlEncoded(String content) { 55 | try { 56 | return URLEncoder.encode(content, OkexSignUtil.INPUT_CHARSET); 57 | } catch (UnsupportedEncodingException e) { 58 | throw new RuntimeException("指定的编码集不对,您目前指定的编码集是:" + OkexSignUtil.INPUT_CHARSET); 59 | } 60 | } 61 | 62 | /** 63 | * url解码 64 | * 65 | * @param content 66 | * @param charset 67 | * @return 68 | */ 69 | public static String urlDecoded(String content, String charset) { 70 | try { 71 | return URLDecoder.decode(content, charset); 72 | } catch (UnsupportedEncodingException e){ 73 | throw new RuntimeException("指定的编码集不对,您目前指定的编码集是:" + charset); 74 | } 75 | } 76 | 77 | public static String urlDecoded(String content) { 78 | try { 79 | return URLDecoder.decode(content, OkexSignUtil.INPUT_CHARSET); 80 | } catch (UnsupportedEncodingException e){ 81 | throw new RuntimeException("指定的编码集不对,您目前指定的编码集是:" + OkexSignUtil.INPUT_CHARSET); 82 | } 83 | } 84 | 85 | /** 86 | * 签名 87 | * 88 | * @param method 请求类型 89 | * @param address ip地址 90 | * @param resourcePath 资源路径 91 | * @param body 请求参数 92 | * @param apiKey 密钥 93 | * @param secretKey 私钥 94 | * @param passPhrase 密码 95 | * @return 96 | */ 97 | public static LinkedHashMap sign(String method, String address, LinkedHashMap body, String resourcePath, String apiKey, String secretKey, String passPhrase) { 98 | 99 | String epoch = formatEpoch(System.currentTimeMillis()); 100 | 101 | StringBuilder s = new StringBuilder(); 102 | s.append(epoch).append(method).append(resourcePath).append(body != null ? OkexUtil.addParams(body) : ""); 103 | String sign = hmacSHA256(s.toString(), secretKey); 104 | 105 | LinkedHashMap lh = new LinkedHashMap(); 106 | lh.put("OK-ACCESS-KEY", apiKey); 107 | lh.put("OK-ACCESS-SIGN", sign); 108 | lh.put("OK-ACCESS-TIMESTAMP", epoch); 109 | lh.put("OK-ACCESS-PASSPHRASE", passPhrase); 110 | lh.put("x-simulated-trading", "1"); 111 | 112 | return lh; 113 | } 114 | 115 | public static String formatEpoch(Long time) { 116 | if (null == time) { 117 | return ""; 118 | } 119 | return String.format("%s.%03d", time / 1000, time % 1000); 120 | } 121 | 122 | 123 | /** 124 | * HmacSHA256 加密 125 | * 126 | * @param msg 加密内容 127 | * @param secretKey 私钥 128 | */ 129 | public static String hmacSHA256(String msg, String secretKey) { 130 | try { 131 | byte [] sign = OkexSignUtil.hmac(msg.getBytes(), secretKey, SIGNATURE_METHOD); 132 | return Base64.getEncoder().encodeToString(sign); 133 | } catch (Exception e) { 134 | System.out.println("Error:"+e.getStackTrace()); 135 | } 136 | return null; 137 | } 138 | 139 | public static byte[] hmac(byte[] message, String key, String algorithm) 140 | throws NoSuchAlgorithmException, InvalidKeyException { 141 | Objects.requireNonNull(message, "message"); 142 | SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), algorithm); 143 | Mac mac = Mac.getInstance(algorithm); 144 | mac.init(signingKey); 145 | return mac.doFinal(message); 146 | } 147 | 148 | /** 149 | * 获取UTC时间 150 | * @param delay 延迟 151 | * @return UTC时间 152 | */ 153 | private static SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd'T'HH:mm:ss"); 154 | private static Date getUTCTimeString() { 155 | Calendar cal = Calendar.getInstance(); 156 | int zoneOffset = cal.get(Calendar.ZONE_OFFSET); 157 | int dstOffset = cal.get(Calendar.DST_OFFSET); 158 | cal.add(Calendar.MILLISECOND, -(zoneOffset + dstOffset)); 159 | return new Date(cal.getTime().getTime()); 160 | } 161 | 162 | 163 | public static void main(String[] args) { 164 | 165 | String appKey = "xx-xx-x-x-x"; 166 | String secret = "xx"; 167 | String address = "https://www.okex.com"; 168 | String passPrase = "123456mzy"; 169 | String body = null; 170 | String resouecePath = "/api/spot/v3/accounts/btc"; 171 | String method = "GET"; 172 | 173 | LinkedHashMap lh = OkexSignUtil.sign(method, address, null, resouecePath, appKey, secret, passPrase); 174 | 175 | OkHttpClient client = new OkHttpClient(); 176 | Request request = new Request.Builder() 177 | .url(address + resouecePath) 178 | .get() 179 | .addHeader("OK-ACCESS-KEY", lh.get("OK-ACCESS-KEY")) 180 | .addHeader("OK-ACCESS-SIGN", lh.get("OK-ACCESS-SIGN")) 181 | .addHeader("OK-ACCESS-TIMESTAMP", lh.get("OK-ACCESS-TIMESTAMP")) 182 | .addHeader("OK-ACCESS-PASSPHRASE", lh.get("OK-ACCESS-PASSPHRASE")) 183 | .build(); 184 | 185 | try (Response response = client.newCall(request).execute()) { 186 | System.out.println(response.body().string()); 187 | } catch (IOException e) { 188 | e.printStackTrace(); 189 | } 190 | 191 | } 192 | 193 | 194 | } 195 | --------------------------------------------------------------------------------