カブロボをJUnitから実行する

JUnitから実行というの作ってみました。
KabuRoboDriverのソースを切り貼りしたものです。


テスト用のヘルパークラスの例

package hoge;

import java.io.PrintStream;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.TimeZone;
import java.util.logging.ConsoleHandler;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;

import jp.kaburobo.information.CachedInformationManagerBuilder;
import jp.kaburobo.information.InformationManager;
import jp.kaburobo.information.InformationManagerBuilder;
import jp.kaburobo.informationprovider.model.IndexDailyDao;
import jp.kaburobo.informationprovider.model.IndexYearlyDao;
import jp.kaburobo.investment.FlexibleInvestmentAgentFactory;
import jp.kaburobo.investment.InvestmentAgent;
import jp.kaburobo.investment.OrderHistory;
import jp.kaburobo.investment.Portfolio;
import jp.kaburobo.robot.Robot;
import jp.kaburobo.search.CachedSearchManagerBuilder;
import jp.kaburobo.search.SearchManager;
import jp.kaburobo.search.SearchManagerBuilder;
import jp.kaburobo.stockserviceprovider.client.IStockAgentClient;
import jp.kaburobo.stockserviceprovider.client.StockAgentClient;
import jp.kaburobo.stockserviceprovider.client.StockAgentDebugClient;
import jp.kaburobo.technical.TechnicalAnalysisManager;
import jp.kaburobo.technical.TechnicalAnalysisManagerBuilder;
import jp.kaburobo.technical.XMLTechnicalAnalysisManagerBuilder;
import jp.kaburobo.util.FixedTimeSetting;
import jp.kaburobo.util.LogFilter;
import jp.kaburobo.util.LoggingStream;
import jp.kaburobo.util.MarketSchedule;
import jp.kaburobo.util.Time;
import jp.kaburobo.util.XMLConfigLoader;

/**
 * @see jp.kaburobo.driver.KabuRoboDriver
 */
public class KaburoboTestManager  {

    private static KaburoboTestManager testManager;
    
    static{
        try{
            testManager = new KaburoboTestManager();
        }catch(Exception e){
            e.printStackTrace();
            throw new IllegalStateException("testManager initilize fail");
        }
    }
    
    
    private DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
    
    private DecimalFormat moneyFormat = new DecimalFormat("###,###,###");
    
    private Logger logger;
    
    private IStockAgentClient stockAgentClient;
    
    private InvestmentAgent investmentAgent;

    private FixedTimeSetting timeSetting;
    
    private Calendar date;
    

    public static KaburoboTestManager getInstance(){
        return testManager;
    }
    
    
    private KaburoboTestManager() {

        try{
            XMLConfigLoader config = XMLConfigLoader.getInstance();
            
        
            PrintStream err = System.err;
            PrintStream out = System.out;
            
            logger = Logger.getLogger("jp.kaburobo.logging");
            logger.setUseParentHandlers(false);
            
            String[] logHandlers = config.getLogHandlers();
            for(int i=0; i<logHandlers.length; i++){
                try{
                    Handler handler = null;
                    if(logHandlers[i].equals("console")){
                        System.setErr(out);
                        handler = new ConsoleHandler();
                        System.setErr(err);
                    } else if(logHandlers[i].equals("file")){
                        String file = config.getLogFile(logHandlers[i]);
                        handler = new FileHandler(file);
                    }
                    if(handler != null){
                        LogFilter outputFilter = new LogFilter();
                        handler.setFilter(outputFilter);
                        
                        String[] filters = config.getFilters(logHandlers[i]);
                        if(filters != null){
                            for(int j=0; j<filters.length; j++){
                                outputFilter.addType(filters[j]);
                            }
                        }
        
                        String formatter = config.getFormatter(logHandlers[i]);
                        try{
                            if(formatter != null){
                                Class c = Class.forName(formatter);
                                handler.setFormatter((Formatter)c.newInstance());
                            }
                        }catch(Exception e){
                            e.printStackTrace();
                        }
                        handler.setLevel(Level.ALL);
                        logger.addHandler(handler);
                    }
                }catch(Exception e){
                    e.printStackTrace();
                }
            }
            logger.setLevel(Level.ALL);
            
            if(config.getRedirect()){
                LoggingStream outStream = new LoggingStream(logger, "output");
                LoggingStream errStream = new LoggingStream(logger, "error");
                System.setOut(outStream);
                System.setErr(errStream);
            }
                    
            long totalStartTime = System.currentTimeMillis();

            TimeZone.setDefault(TimeZone.getTimeZone("Asia/Tokyo"));
            date = (Calendar)config.getStartDate().clone();
            Calendar endDate = config.getEndDate();

//            Interval interval = new Interval(date, endDate);
//            Calendar[] validDates = MarketSchedule.getInstance().getDates(interval);
//            int index=0;
            
            timeSetting = new FixedTimeSetting();
            timeSetting.setTime(date);
            Time.setTimeSetting(timeSetting);

            InformationManagerBuilder builder = new CachedInformationManagerBuilder();
            InformationManager informationManager = builder
                    .createInformationManager();

            TechnicalAnalysisManagerBuilder tbuilder = new XMLTechnicalAnalysisManagerBuilder();
            TechnicalAnalysisManager technicalManager = tbuilder.createTechnicalAnalysisManager();

            SearchManagerBuilder sbuilder = new CachedSearchManagerBuilder();
            SearchManager searchManager = sbuilder.createSearchManager();
            
            if(config.getParameter("stockserver", "url") != null){
                stockAgentClient= new StockAgentClient(
                        config.getParameter("stockserver", "id"),
                        config.getParameter("stockserver", "password"),
                        config.getParameter("stockserver", "url"));
            } else {
                String id =  config.getParameter("stockserver", "id");
                String password =  config.getParameter("stockserver", "password");

                String infojdbc = config.getParameter("information", "jdbc");
                String infourl =  config.getParameter("information", "url");
                String infoid =  config.getParameter("information", "id");
                String infopassword =  config.getParameter("information", "password");
                
                IndexYearlyDao indexYearlyDao = 
                    new IndexYearlyDao (infojdbc, infourl, infoid, infopassword);
                IndexDailyDao indexDaylyDao = 
                    new IndexDailyDao (infojdbc, infourl, infoid, infopassword);

                stockAgentClient= new StockAgentDebugClient(
                        id, password, indexYearlyDao, indexDaylyDao);
            }

            // リセット処理
            stockAgentClient.reset();
            
            FlexibleInvestmentAgentFactory factory = new FlexibleInvestmentAgentFactory();
            factory.setInformationManager(informationManager);
            factory.setTechnicalAnalysisManager(technicalManager);
            factory.setSearchManager(searchManager);
            factory.setStockAgentClient(stockAgentClient);

            investmentAgent = factory.createInvestmentAgent();

        }catch(Exception e){
            e.printStackTrace();
            throw new IllegalStateException();
        }
    }
    
    

    public IStockAgentClient getAgentClient(){
        return stockAgentClient;
    }
    
    public void setDate(Date newDate){
        date.setTime(newDate);
        timeSetting.setTime(date);
    }

    
    
    
    /**
     * カブロボを実行して一日進める
     * ログも表示
     */
    public void runRobot(Robot robot){
    
        try{ 
            String strDate = dateFormat.format(date.getTime());
        
            logger.log(Level.INFO, "DAY: "+strDate, "driver");
        
    
            Portfolio portfolio = investmentAgent.getPortfolio();
            logger.log(Level.INFO,
                    "資金: "+moneyFormat.format(portfolio.getMoney())+"pts "
                        +"取引可能金額: "+moneyFormat.format(portfolio.getAvailableMoney())+"pts\n",
                    "driver");
    
            
            
            
            if(MarketSchedule.getInstance().checkSchedule(date)){

                
                //実行
                robot.run(investmentAgent);
                //
                
                
                Calendar execDate = getNearlyMarketDate();
                
                stockAgentClient.orderExec(execDate.getTime());
                            
                // 注文結果出力
                List list = investmentAgent.getOrderResult(date);
                Iterator itr = list.iterator();
                if(itr.hasNext()){
                    String strResult = "\n【当日注文処理結果】\n";
                    strResult += "銘柄|取引単位数|値段\n";
                    strResult += "----+----------+----\n";
                    while(itr.hasNext()){
                        jp.kaburobo.investment.OrderResult result = (jp.kaburobo.investment.OrderResult)itr.next();

                        
                        String str = ""+result.getStockCode();
                        for(int j=str.length(); j<4; j++){
                            str = " "+str;
                        }
                        strResult += str+"|";

                        str = ""+result.getNumber();
                        for(int j=str.length(); j<10; j++){
                            str = " "+str;
                        }
                        strResult += str+"|";
                        
                        if(result.getNumber() != 0){
                            strResult += result.getSuccessPrice()+"\n";
                        } else {
                            strResult += " - \n";
                        }
                    }
                    logger.log(Level.INFO, strResult, "result");
                }                
                
            }else{
                logger.log(Level.INFO, "休日");
            }

            
            addDate();
            
        }catch(Exception e){
            e.printStackTrace();
            throw new IllegalStateException("fail to run robot");
        }
    }
    
    
    private Calendar getNearlyMarketDate(){
        Calendar execDate = (Calendar)date.clone();

        for(;;){
            execDate.add(Calendar.DATE, 1);
            if(MarketSchedule.getInstance().checkSchedule(execDate)){
                break;
            }
        }
        return execDate;
    }


    
    /**
     * 指定した日からdays日間(休日含む)ロボット実行
     */
    public void runRobotFrom(Robot robot, String startDate, int days){
        setDateByText(startDate);
        for(int i=0; i<days; i++){
            runRobot(robot);
        }
    }
    
    
    public void dumpOrderHistories(){
        OrderHistory[] histories = investmentAgent.getOrderHistory();
        String strHistory = "【履歴】\n";
        for(int i=0; i<histories.length; i++){
            strHistory += 
                dateFormat.format(histories[i].getDate().getTime())+" "
                +"資金: "+moneyFormat.format(histories[i].getMoney())+"pts "
                +"評価額: "+moneyFormat.format(histories[i].getAmount())+"pts\n";
        }
        logger.log(Level.INFO, strHistory, "history");
    }
    
    
    
    
    public InvestmentAgent getInvestmentAgent(){
        return investmentAgent;
    }
    
    
    
    
    /**
     * yyyy/MM/dd
     */
    public void setDateByText(String dateText){
        try{
                        
            Date newDate = dateFormat.parse(dateText);
            setDate(newDate);
        }catch(Exception e){
            e.printStackTrace();
            throw new IllegalStateException("date parse fail");
        }
    }
    
    public void addDate(){
        date.add(Calendar.DATE, 1);
        timeSetting.setTime(date);
    }

}


テストケースの例

package hoge;

import junit.framework.TestCase;

import com.muimi.kaburobo.MyRobot;


public class KabuRoboTestCase extends TestCase {

    
    public void testFoo(){

        KaburoboTestManager manager = KaburoboTestManager.getInstance();
        manager.runRobotFrom(new MyRobot(), "2004/04/01", 30);
        manager.dumpOrderHistories();
        
    }
    

    public void testBar(){

        KaburoboTestManager manager = KaburoboTestManager.getInstance();
        manager.setDateByText("2004/04/01");
        manager.runRobot(new MyRobot());
        
    }

}


ちょっと結果確認ってしずらいので、単なるランチャー気分かも。
日付は自由に切り替えられます。
結局DBにいろんなデータとりにいくので、ちゃんとやろうとすると、DBにテストデータをセッティングする必要があるかもないかも。。。


なお、実行にはVM引数に kaburobo.home を指定する必要があります。

  • Dkaburobo.home=C:\data\projects\kaburobo\kaburobo_ver_1_2_5\kaburobo

もちろんjunit.jarやカブロボのjarもクラスパスに必要。