package jforex;

import com.dukascopy.api.*;
import com.dukascopy.api.Configurable;
import com.dukascopy.api.IAccount;
import com.dukascopy.api.IBar;
import com.dukascopy.api.IConsole;
import com.dukascopy.api.IContext;
import com.dukascopy.api.IEngine.OrderCommand;
import com.dukascopy.api.IEngine;
import com.dukascopy.api.IHistory;
import com.dukascopy.api.IIndicators;
import com.dukascopy.api.IMessage.Type;
import com.dukascopy.api.IMessage;
import com.dukascopy.api.IOrder;
import com.dukascopy.api.IStrategy;
import com.dukascopy.api.ITick;
import com.dukascopy.api.IUserInterface;
import com.dukascopy.api.Instrument;
import com.dukascopy.api.JFException;
import com.dukascopy.api.OfferSide;
import com.dukascopy.api.Period;
import java.util.*;
import java.util.ArrayList;
import java.text.NumberFormat;
import java.math.BigDecimal;
import java.math.RoundingMode;
import com.dukascopy.api.indicators.*;
import com.dukascopy.api.IIndicators.AppliedPrice;
import com.dukascopy.api.feed.*;
import java.io.*;
import java.text.*;
@RequiresFullAccess

public class _03LongOrShortMoveSL implements IStrategy {
    @Configurable(value = "货币对", description = "货币对") 
    public Instrument minstrument = Instrument.XAUUSD;   
    @Configurable(value = "周期", description = "跟踪止损周期")
    public Period mPeriod =Period.ONE_MIN;
   @Configurable(value = "止损偏移量", description = "止损偏移量")
   public double stopLossStepPips=65;
     @Configurable(value = "止损加速", description = "止损加速")
    public double stopLossA =0.0024;
    @Configurable(value = "止损最大", description = "止损最大")
    public double  stopLossMax= 0.1;
    @Configurable(value = "多止损输出文件", description = "输出文件")
    public File Longfile;
    @Configurable(value = "空止损输出文件", description = "输出文件")
    public File Shortfile;
   @Configurable(value = "外部计算", description = "外部计算")
    public boolean  isWaiCal;
    @Configurable(value = "输入文件", description = "输入文件")
    public File infile;
    
   // private Writer out;
    private Reader inm;
    
    private IEngine engine;
    private IConsole console;
    private IHistory history;
    private IContext context;
    private IIndicators indicators;
    private IUserInterface userInterface;
    private IChart Chart;
    private List<IOrder> orderlist=new ArrayList<IOrder>();
    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();
         Chart=context.getLastActiveChart();
        console.getOut().println( Chart.getSelectedPeriod()); 
        console.getOut().println( Chart.getFeedDescriptor()); 
    }

    public void onAccount(IAccount account) throws JFException {
    }

    public void onMessage(IMessage message) throws JFException {
    }

    public void onStop() throws JFException {
    }

    public void onTick(Instrument instrument, ITick tick) throws JFException {
    }
    
    public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {
                  if(instrument != this.minstrument || period != this.mPeriod){
                    return;
                  }
            try{
                
                  double  mPipValue=instrument.getPipValue();
                  double sarValue=0;
                  if(isWaiCal==false)
                 { 
                      long prevBarTime = history.getPreviousBarStart(mPeriod, history.getLastTick(minstrument).getTime());
                      long startTime =  history.getTimeForNBarsBack(mPeriod, prevBarTime,0); 
                      long timeFrom =startTime ; 
                      long timeTo =startTime ;
                      console.getOut().println( new Date(prevBarTime));
                      console.getOut().println( new Date(startTime));
                       FeedDescriptor feedDescriptor = new FeedDescriptor();
                         feedDescriptor.setDataType(DataType.TIME_PERIOD_AGGREGATION);        
                         feedDescriptor.setFilter(Filter.ALL_FLATS);
                         feedDescriptor.setInstrument(minstrument);
                         feedDescriptor.setPeriod(mPeriod);
                        
                          Object[] result = indicators.calculateIndicator(
                           feedDescriptor, 
                           new OfferSide[] {OfferSide.BID},
                           "SAR", 
                           new AppliedPrice[] { AppliedPrice.CLOSE },
                           new Object[] {stopLossA,stopLossMax},
                           timeFrom,
                           timeTo);    
                        sarValue=((double[])result[0])[0];
                        console.getOut().println("内部计算:"+sarValue);
                 }else{
                       try{
                            if(infile == null || infile.getPath().equals(""))
                             {
                                  console.getErr().println("没有选择外部计算文件");
                                  context.stop();
                                  return;
                             }else{
                                 BufferedReader bufRdr  = new BufferedReader(new FileReader(infile));
                                 String line = bufRdr.readLine();
                                 bufRdr.close();
                                 if(line==null||line.equals(""))
                                 {
                                      console.getErr().println("外部计算无数据!");
                                      context.stop();
                                      return;
                                 }else{
                                     sarValue=Double.parseDouble(line); 
                                     console.getOut().println("外部计算:"+line);
                                 }
                             }
                          }catch (NoSuchElementException nsee){
                          }        
                  }
                 double outstopLoss=sarValue;
                  if(Longfile == null || Longfile.getPath().equals(""))
                  {
                        console.getErr().println("没有选择多止损输出文件");
                    }else{
                        
                         double longstopLoss=sarValue-outstopLoss*mPipValue;
                         BigDecimal longbd=CalBd(longstopLoss,instrument);   
                        try {
                            Writer  out = new BufferedWriter(new FileWriter(Longfile));
                            console.getOut().println("多止损数据交换开始.....");
                            console.getOut().println("多止损:"+String.valueOf(longbd));
                            out.write(String.valueOf(longbd));
                            out.close();
                            console.getOut().println("多止损数据交换完成!");
                        } catch (Exception e) {
                         console.getErr().println(e.getMessage());
                         e.printStackTrace(console.getErr());
                        }
                    }
                 if(Shortfile == null || Shortfile.getPath().equals(""))
                  {
                      console.getErr().println("没有选择空止损输出文件");
                      
                  }else{
                        
                         double shortstopLoss=sarValue+stopLossStepPips*mPipValue;   
                          BigDecimal shortbd=CalBd(shortstopLoss,instrument);   
                          try {
                           Writer out2 = new BufferedWriter(new FileWriter(Shortfile));
                            console.getOut().println("空止损数据交换开始.....");
                            console.getOut().println("空止损:"+String.valueOf(shortbd));
                            out2.write(String.valueOf(shortbd));
                            out2.close();
                            console.getOut().println("空止损数据交换完成!");
                        } catch (Exception e) {
                         console.getErr().println(e.getMessage());
                         e.printStackTrace(console.getErr());
                        } 
                  }
                  
                  //获得订单
                  //double stopLoss=sarValue+stopLossStepPips*mPipValue;
                  console.getOut().println("开始执行止损移动.....");
                   double stopLoss=sarValue;
                   orderlist = engine.getOrders(minstrument);
                   if(orderlist.size()==0){
                      console.getOut().println("没有订单!");
                      return;
                   }
                   
                   for(int i=0;i<orderlist.size();i++)
                    {
                       IOrder mo;
                       mo=(IOrder)orderlist.get(i);
                     
                      if( mo.getState() == IOrder.State.FILLED)//已经执行的单子
                      {
                          //对比现在价格跟SAR关系
                          console.getOut().println("onBar止损基数:"+sarValue);
                          if(mo.isLong()){//多单
                               console.getOut().println("多单订单:"+mo.getId());
                               if(bidBar.getClose()<sarValue){
                                  console.getOut().println("多单不能移动止损!");
                                 break;
                               }
                              stopLoss=sarValue-stopLossStepPips*mPipValue;
                              BigDecimal bd=CalBd(stopLoss,instrument);   
                              mo.setStopLossPrice(Double.parseDouble(bd.toString()), OfferSide.BID);
                              console.getOut().println("修改多单止损:"+bd);  
                             
                              
                          }
                          else{
                                 console.getOut().println("空单订单:"+mo.getId());
                                  if(bidBar.getClose()>sarValue){
                                      console.getOut().println("空单不能移动止损!");
                                      break;
                                  }
                                  stopLoss=sarValue+stopLossStepPips*mPipValue;   
                                   BigDecimal bd=CalBd(stopLoss,instrument);             
                                   mo.setStopLossPrice(Double.parseDouble(bd.toString()), OfferSide.BID);
                                   console.getOut().println("修改空单止损:"+bd);  
                          }      
                      }
                    }  
                             
           }
           catch (Exception e) {
               e.printStackTrace(console.getErr()); 
           }
           
      
    }
   public BigDecimal CalBd(double stPrice,Instrument instrument)
   {
       BigDecimal bd=new BigDecimal(stPrice);
       if(minstrument==instrument.XAUUSD){
             bd=bd.setScale(2, BigDecimal.ROUND_HALF_UP);
        } else{
             bd=bd.setScale(5, BigDecimal.ROUND_HALF_UP);
        }
        return bd;
   }
   
}