package stoploss;
import com.dukascopy.api.*;
import java.util.HashSet;
import java.util.Set;
import com.dukascopy.api.drawings.IChartObjectFactory;
import com.dukascopy.api.drawings.IOhlcChartObject;
import com.dukascopy.api.indicators.OutputParameterInfo.DrawingStyle;
import java.awt.Color;
import java.awt.Dimension;
import java.util.HashMap;
import java.util.Map;
import com.dukascopy.api.drawings.IChartDependentChartObject;
import com.dukascopy.api.drawings.ITriangleChartObject;
import com.dukascopy.api.drawings.ITextChartObject;
public class StopLossStrategy implements IStrategy {
private IEngine engine;
private IConsole console;
private IHistory history;
private IContext context;
private IIndicators indicators;
private IUserInterface userInterface;
private IBar previousBar;
private IOrder order;
private IChart openedChart;
private IChartObjectFactory factory;
private int signals;
private static final int PREV = 1;
private static final int SECOND_TO_LAST = 0;
private int uniqueOrderCounter = 1;
private SMATrend previousSMADirection = SMATrend.NOT_SET;
private SMATrend currentSMADirection = SMATrend.NOT_SET;
private Map<IOrder, Boolean> createdOrderMap = new HashMap<IOrder, Boolean>();
private int shorLineCounter;
private int textCounterOldSL;
private int textCounterNewSL;
@Configurable( value = "通貨ペア" )
public Instrument myInstrument = Instrument.EURGBP;
@Configurable( value = "オーダータイプ", obligatory = true )
public OfferSide myOfferSide = OfferSide.ASK;
@Configurable( value = "時間軸" )
public Period myPeriod = Period.TEN_MINS;
@Configurable( "SMA期間" )
public int smaTimePeriod = 30;
@Configurable("チャート上にOHLCインデックス表示")
public boolean addOHLC = true;
@Configurable("フィルター")
public Filter filter = Filter.WEEKENDS;
@Configurable("SMA描画")
public boolean drawSMA = true;
@Configurable("ストラテジー停止時にチャートを閉じる")
public boolean closeChart;
@Configurable("ストップロス(pips)")
public int stopLossPips = 10;
@Configurable("リミット(pips)")
public int takeProfitPips = 10;
@Configurable("ブレークイーブン(pips)")
public double breakEventPips = 5;
private enum SMATrend {
UP, DOWN, NOT_SET;
}
public void onStart(IContext context) throws JFException {
this.engine = context.getEngine();
this.console = context.getConsole();
this.history = context.getHistory();
this.context = context;
this.indicators = context.getIndicators();
this.userInterface = context.getUserInterface();
this.openedChart = context.getChart(myInstrument);
this.factory = openedChart.getChartObjectFactory();
Set<Instrument> instruments = new HashSet<Instrument>();
instruments.add(myInstrument);
context.setSubscribedInstruments(instruments, true);
if( drawSMA ) {
if( !addToChart(openedChart) ){
printMeError("チャート上にインジケータをプロット出来ませんでした。チャートの設定値を確認して下さい。");
}
}
}
public void onAccount(IAccount account) throws JFException {
}
public void onMessage(IMessage message) throws JFException {
if( message.getOrder() != null )
console.getOut().println("オーダーラベル: " + message.getOrder().getLabel()
+ " || メッセージログ: " + message.getContent());
}
public void onStop() throws JFException {
if( closeChart )
context.closeChart(openedChart);
}
public void onTick(Instrument instrument, ITick tick) throws JFException {
if ( instrument != myInstrument) {
return;
}
for ( Map.Entry<IOrder, Boolean> entry : createdOrderMap.entrySet() ) {
IOrder currentOrder = entry.getKey();
boolean currentValue = entry.getValue();
if ( currentValue == false && currentOrder.getProfitLossInPips() >= breakEventPips ) {
printMe( currentOrder.getProfitLossInPips() + "pipsリミットのポジションのストップロスはエントリーレートに移動しました。");
addBreakToChart( currentOrder, tick, currentOrder.getStopLossPrice(), currentOrder.getOpenPrice() );
currentOrder.setStopLossPrice( currentOrder.getOpenPrice() );
entry.setValue( true );
}
}
}
public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {
if (!instrument.equals(myInstrument) || !period.equals(myPeriod)) {
return;
}
int candlesBefore = 2, candlesAfter = 0;
long completedBarTimeL = myOfferSide == OfferSide.ASK ? askBar.getTime() : bidBar.getTime();
double sma[] = indicators.sma(instrument, period, myOfferSide, IIndicators.AppliedPrice.CLOSE,
smaTimePeriod, Filter.NO_FILTER, candlesBefore, completedBarTimeL, candlesAfter);
IEngine.OrderCommand myCommand = null;
printMe( String.format("SMAの値: 2つ前 = %.5f; 1つ前 = %.5f", sma[SECOND_TO_LAST], sma[PREV]));
if( sma[PREV] > sma[SECOND_TO_LAST]){
printMe("SMA上昇");
myCommand = IEngine.OrderCommand.BUY;
currentSMADirection = SMATrend.UP;
} else if ( sma[PREV] < sma[SECOND_TO_LAST]){
printMe("SMA下降");
myCommand = IEngine.OrderCommand.SELL;
currentSMADirection = SMATrend.DOWN;
} else {
return;
}
double lastTickBid = history.getLastTick(myInstrument).getBid();
double lastTickAsk = history.getLastTick(myInstrument).getAsk();
double stopLossValueForLong = myInstrument.getPipValue() * stopLossPips;
double stopLossValueForShort = myInstrument.getPipValue() * takeProfitPips;
double stopLossPrice = myCommand.isLong() ? (lastTickBid - stopLossValueForLong ) : (lastTickAsk + stopLossValueForLong);
double takeProfitPrice = myCommand.isLong() ? (lastTickBid + stopLossValueForShort) : (lastTickAsk - stopLossValueForShort);
if ( currentSMADirection != previousSMADirection ) {
previousSMADirection = currentSMADirection;
IOrder newOrder = engine.submitOrder("MyStrategyOrder" + uniqueOrderCounter++, instrument, myCommand,
0.001, 0, 1, stopLossPrice, takeProfitPrice);
createdOrderMap.put(newOrder, false);
if( openedChart == null ){
return;
}
long time = bidBar.getTime() + myPeriod.getInterval();
double space = myInstrument.getPipValue() * 2;
IChartDependentChartObject signal = myCommand.isLong()
? factory.createSignalUp( "signalUpKey" + signals++, time, bidBar.getLow() - space)
: factory.createSignalDown("signalDownKey" + signals++, time, bidBar.getHigh() + space);
signal.setStickToCandleTimeEnabled(false);
signal.setText("MyStrategyOrder" + (uniqueOrderCounter - 1));
openedChart.addToMainChart(signal);
}
}
private void printMe(Object toPrint){
console.getOut().println(toPrint);
}
private void printMeError(Object o){
console.getErr().println(o);
}
private boolean addToChart(IChart chart){
if ( !checkChart(chart) ) {
return false;
}
chart.addIndicator(indicators.getIndicator("SMA"), new Object[] {smaTimePeriod},
new Color[]{Color.BLUE}, new DrawingStyle[]{DrawingStyle.LINE}, new int[]{3});
if(addOHLC){
IOhlcChartObject ohlc = null;
for (IChartObject obj : chart.getAll()) {
if (obj instanceof IOhlcChartObject) {
ohlc = (IOhlcChartObject) obj;
}
}
if (ohlc == null) {
ohlc = chart.getChartObjectFactory().createOhlcInformer();
ohlc.setPreferredSize(new Dimension(100, 200));
chart.addToMainChart(ohlc);
}
ohlc.setShowIndicatorInfo(true);
}
return true;
}
private void addBreakToChart(IOrder changedOrder, ITick tick, double oldSL, double newSL) throws JFException {
if ( openedChart == null ) {
return;
}
ITriangleChartObject orderSLTriangle = factory.createTriangle("Triangle " + shorLineCounter++,
changedOrder.getFillTime(), changedOrder.getOpenPrice(), tick.getTime(), oldSL, tick.getTime(), newSL);
Color lineColor = oldSL > newSL ? Color.RED : Color.GREEN;
orderSLTriangle.setColor(lineColor);
orderSLTriangle.setLineStyle(LineStyle.SOLID);
orderSLTriangle.setLineWidth(1);
orderSLTriangle.setStickToCandleTimeEnabled(false);
openedChart.addToMainChart(orderSLTriangle);
String breakTextOldSL = String.format(" Old SL: %.5f", oldSL);
String breakTextNewSL = String.format(" New SL: %.5f", newSL);
double textVerticalPosition = oldSL > newSL ? newSL - myInstrument.getPipValue() : newSL + myInstrument.getPipValue();
ITextChartObject textOldSL = factory.createText("textKey1" + textCounterOldSL++, tick.getTime(), oldSL);
ITextChartObject textNewSL = factory.createText("textKey2" + textCounterNewSL++, tick.getTime(), newSL);
textOldSL.setText(breakTextOldSL);
textNewSL.setText(breakTextNewSL);
textOldSL.setStickToCandleTimeEnabled(false);
textNewSL.setStickToCandleTimeEnabled(false);
openedChart.addToMainChart(textOldSL);
openedChart.addToMainChart(textNewSL);
}
private boolean checkChart(IChart chart) {
if (chart == null ) {
printMeError( myInstrument + " のチャートが開かれていません");
return false;
}
if (chart.getSelectedOfferSide() != this.myOfferSide) {
printMeError( "チャートのオーダータイプ(アスク/ビッド)と一致していません:" + this.myOfferSide);
return false;
}
if (chart.getSelectedPeriod() != this.myPeriod) {
printMeError(this.myPeriod + "の時間軸チャートが開かれていません。");
return false;
}
if (chart.getFilter() != this.filter) {
printMeError("chart filter is not " + this.filter);
return false;
}
return true;
}
}