package feed;
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;
import com.dukascopy.api.IIndicators.AppliedPrice;
import com.dukascopy.api.feed.IFeedDescriptor;
import com.dukascopy.api.feed.IFeedListener;
import com.dukascopy.api.feed.util.RenkoFeedDescriptor;
import com.dukascopy.api.feed.util.TimePeriodAggregationFeedDescriptor;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
public class FeedsGUI implements IStrategy, IFeedListener {
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;
private boolean dialogClosed = true;
private JOptionPane optionPane = new JOptionPane(null, JOptionPane.WARNING_MESSAGE);
private JDialog dialog = optionPane.createDialog( null, null ) ;
@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;
@Configurable( "SMA期間" )
public int smaTimePeriod = 30;
@Configurable("フィードタイプ")
public FeedType myFeed = FeedType.RENKO_2_PIPS_EURGBP_BID;
private enum SMATrend {
UP, DOWN, NOT_SET;
}
public enum FeedType {
RENKO_2_PIPS_EURGBP_BID ( new RenkoFeedDescriptor(Instrument.EURGBP, PriceRange.TWO_PIPS, OfferSide.BID)),
TIME_BAR_30_SEC_EURGBP_BID (new TimePeriodAggregationFeedDescriptor(Instrument.EURGBP, Period.THIRTY_SECS,
OfferSide.BID, Filter.WEEKENDS));
private final IFeedDescriptor feedDescriptor;
FeedType(IFeedDescriptor feedDescriptor) {
this.feedDescriptor = feedDescriptor;
}
public IFeedDescriptor getFeedDescriptor(){
return feedDescriptor;
}
}
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(myFeed.getFeedDescriptor().getInstrument());
this.factory = openedChart.getChartObjectFactory();
Set<Instrument> instruments = new HashSet<Instrument>();
instruments.add(myFeed.getFeedDescriptor().getInstrument());
context.setSubscribedInstruments(instruments, true);
if( drawSMA ) {
if( !addToChart(openedChart) ){
printMeError("チャート上にインジケータをプロット出来ませんでした。チャートの設定値を確認して下さい。");
}
}
context.subscribeToFeed(myFeed.getFeedDescriptor(), this);
dialog.setModal( false );
}
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 {
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 );
}
}
}
@Override
public void onFeedData(IFeedDescriptor feedDescriptor, ITimedData feedData) {
Instrument myInstrument = feedDescriptor.getInstrument();
OfferSide myOfferSide = feedDescriptor.getOfferSide();
try {
if ( !(feedData instanceof IBar) ) {
printMeError("ティックフィードデータは使えません。");
return;
}
IBar bar = (IBar) feedData;
int candlesBefore = 2, candlesAfter = 0;
long completedBarTimeL = bar.getTime();
Object[] smaObjectsFeed = indicators.calculateIndicator(feedDescriptor, new OfferSide[]{myOfferSide}, "SMA",
new AppliedPrice[]{AppliedPrice.CLOSE}, new Object[]{smaTimePeriod}, candlesBefore,
feedData.getTime(), candlesAfter);
double[] sma = (double[]) smaObjectsFeed[0];
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++, myInstrument, myCommand,
0.001, 0, 1, stopLossPrice, takeProfitPrice);
createdOrderMap.put(newOrder, false);
SwingUtilities.invokeLater( new Runnable(){
public void run(){
showNotification();
}
});
if( openedChart == null ){
return;
}
long time = history.getFeedData(feedDescriptor, 0).getTime();
double space = myInstrument.getPipValue() * 2;
IChartDependentChartObject signal = myCommand.isLong()
? factory.createSignalUp( "signalUpKey" + signals++, time, bar.getLow() - space)
: factory.createSignalDown("signalDownKey" + signals++, time, bar.getHigh() + space);
signal.setText("MyStrategyOrder" + (uniqueOrderCounter - 1));
openedChart.addToMainChart(signal);
}
} catch (Exception e) {
}
}
public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {
}
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 pipValue = myFeed.getFeedDescriptor().getInstrument().getPipValue();
double textVerticalPosition = oldSL > newSL ? newSL - pipValue : newSL + pipValue;
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( myFeed.getFeedDescriptor().getInstrument() + " のチャートが開かれていません。" );
return false;
}
if (chart.getSelectedOfferSide() != myFeed.getFeedDescriptor().getOfferSide()) {
printMeError( myFeed.getFeedDescriptor().getOfferSide() + "のオーダータイプのチャートが開かれていません。" );
return false;
}
if (chart.getFeedDescriptor().getDataType() == DataType.RENKO) {
if (chart.getPriceRange() != myFeed.getFeedDescriptor().getPriceRange()) {
printMeError(myFeed.getFeedDescriptor().getPriceRange() + "の価格期間のチャートが開かれていません。" );
return false;
}
} else if (chart.getFeedDescriptor().getDataType() == DataType.TIME_PERIOD_AGGREGATION) {
if (chart.getSelectedPeriod() != myFeed.getFeedDescriptor().getPeriod()) {
printMeError( myFeed.getFeedDescriptor().getPeriod() + "の時間軸のチャートが開かれていません。" );
return false;
}
}
if (chart.getFilter() != this.filter) {
printMeError( this.filter + "のチャートフィルターではありません " );
return false;
}
return true;
}
private void showNotification(){
String message = "MyStrategyOrderオーダーは" + (uniqueOrderCounter -1) + "回作成されました。";
if( dialogClosed ){
dialog.addComponentListener(new ComponentAdapter() {
public void componentHidden(ComponentEvent e){
dialogClosed = true;
}
});
optionPane.setMessage(message);
dialog.setVisible(true);
dialogClosed = false;
} else {
optionPane.setMessage(message);
dialog.validate();
}
}
}