forked from dromara/northstar
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
fe6bb96
commit 5de6bbc
Showing
1 changed file
with
138 additions
and
0 deletions.
There are no files selected for viewing
138 changes: 138 additions & 0 deletions
138
...strategy-example/src/main/java/org/dromara/northstar/strategy/OpenningHelperStrategy.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
package org.dromara.northstar.strategy; | ||
|
||
import java.util.List; | ||
import java.util.Objects; | ||
import java.util.Optional; | ||
|
||
import org.dromara.northstar.common.constant.FieldType; | ||
import org.dromara.northstar.common.constant.ModuleState; | ||
import org.dromara.northstar.common.model.DynamicParams; | ||
import org.dromara.northstar.common.model.Setting; | ||
import org.dromara.northstar.common.model.core.Contract; | ||
import org.dromara.northstar.common.model.core.Tick; | ||
import org.dromara.northstar.common.model.core.Trade; | ||
import org.dromara.northstar.common.utils.FieldUtils; | ||
import org.dromara.northstar.common.utils.TradeHelper; | ||
import org.slf4j.Logger; | ||
|
||
import cn.hutool.core.lang.Assert; | ||
import lombok.Getter; | ||
import lombok.Setter; | ||
|
||
@StrategicComponent(OpenningHelperStrategy.NAME) | ||
public class OpenningHelperStrategy extends AbstractStrategy implements TradeStrategy{ | ||
|
||
public static final String NAME = "开仓助手"; | ||
|
||
InitParams params; // 策略的参数配置信息 | ||
|
||
Contract tradeContract; | ||
Contract indexContract; | ||
|
||
TradeHelper helper; | ||
|
||
Double buyTrigger; | ||
Double sellTrigger; | ||
Double buyStop; | ||
Double sellStop; | ||
|
||
Logger logger; | ||
|
||
@Override | ||
protected void initIndicators() { | ||
logger = ctx.getLogger(getClass()); | ||
List<Contract> contracts = ctx.bindedContracts(); | ||
if(contracts.size() == 1){ | ||
tradeContract = contracts.get(0); | ||
} else if(contracts.size() == 2){ | ||
contracts.stream().filter(c -> c.name().contains("指数")).findAny().ifPresent(c -> indexContract = c); | ||
contracts.stream().filter(c -> c.tradable()).findAny().ifPresent(c -> tradeContract = c); | ||
Assert.notNull(indexContract, "指数合约为空"); | ||
Assert.notNull(tradeContract, "交易合约为空"); | ||
} else { | ||
throw new IllegalArgumentException("只能绑定不多于两个合约"); | ||
} | ||
|
||
helper = TradeHelper.builder().context(ctx).tradeContract(tradeContract).build(); | ||
logger = ctx.getLogger(getClass()); | ||
|
||
if(params.buyTriggerPrice > 0) | ||
buyTrigger = params.buyTriggerPrice; | ||
if(params.sellTriggerPrice > 0) | ||
sellTrigger = params.sellTriggerPrice; | ||
if(params.buyStopPrice > 0) | ||
buyStop = params.buyStopPrice; | ||
if(params.sellStopPrice > 0) | ||
sellStop = params.sellStopPrice; | ||
} | ||
|
||
@Override | ||
public void onTick(Tick tick) { | ||
Contract c = Optional.ofNullable(indexContract).orElse(tradeContract); | ||
if(!c.equals(tick.contract())) { | ||
return; | ||
} | ||
if(ctx.getState().isEmpty()) { | ||
if(Objects.nonNull(buyTrigger) && tick.lastPrice() <= buyTrigger && tick.lastPrice() > params.buyStopPrice) { | ||
helper.doBuyOpen(ctx.getDefaultVolume()); | ||
return; | ||
} | ||
if(Objects.nonNull(sellTrigger) && tick.lastPrice() >= sellTrigger && tick.lastPrice() < params.sellStopPrice) { | ||
helper.doSellOpen(ctx.getDefaultVolume()); | ||
return; | ||
} | ||
} | ||
if(ctx.getState() == ModuleState.HOLDING_SHORT && Objects.nonNull(sellStop) && tick.lastPrice() >= sellStop) { | ||
helper.doBuyClose(ctx.getDefaultVolume()); | ||
} | ||
if(ctx.getState() == ModuleState.HOLDING_LONG && Objects.nonNull(buyStop) && tick.lastPrice() <= buyStop) { | ||
helper.doSellClose(ctx.getDefaultVolume()); | ||
} | ||
} | ||
|
||
@Override | ||
public void onTrade(Trade trade) { | ||
if(params.reverse && FieldUtils.isClose(trade.offsetFlag())) { | ||
switch(trade.direction()) { | ||
case D_Buy -> helper.doBuyOpen(trade.volume()); | ||
case D_Sell -> helper.doSellOpen(trade.volume()); | ||
default -> throw new IllegalArgumentException("Unexpected value: " + trade.direction()); | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public DynamicParams getDynamicParams() { | ||
return new InitParams(); | ||
} | ||
|
||
@Override | ||
public void initWithParams(DynamicParams params) { | ||
this.params = (InitParams) params; | ||
} | ||
|
||
@Setter | ||
@Getter | ||
public static class InitParams extends DynamicParams { | ||
|
||
@Setting(label="多头触发价", order=1) | ||
private double buyTriggerPrice; | ||
|
||
@Setting(label="多头止损价", order=2) | ||
private double buyStopPrice; | ||
|
||
@Setting(label="空头触发价", order=3) | ||
private double sellTriggerPrice; | ||
|
||
@Setting(label="空头止损价", order=4) | ||
private double sellStopPrice; | ||
|
||
@Setting(label="反手", type = FieldType.SELECT, options = {"是", "否"}, optionsVal = {"true", "false"}, order=5) | ||
private boolean reverse; | ||
} | ||
|
||
@Override | ||
public String name() { | ||
return NAME; | ||
} | ||
} |