diff --git a/src/main/java/ats/plugin/CandlestickWindow.java b/src/main/java/ats/plugin/CandlestickWindow.java new file mode 100644 index 0000000..ee2daf6 --- /dev/null +++ b/src/main/java/ats/plugin/CandlestickWindow.java @@ -0,0 +1,17 @@ +package ats.plugin; + +import org.joda.time.DateTime; + +/** + * A CandlestickWindow runs a CandlestickCalc across a number of + * ticks and sends + */ +interface CandlestickWindow { + public enum Type { time, ticks }; + + /** + * Process a tick with the given time and value. + */ + public void update(DateTime timestamp, double value); + +} diff --git a/src/main/java/ats/plugin/OHLCPlugInView.java b/src/main/java/ats/plugin/OHLCPlugInView.java index 3a3a2fe..3c7548c 100644 --- a/src/main/java/ats/plugin/OHLCPlugInView.java +++ b/src/main/java/ats/plugin/OHLCPlugInView.java @@ -22,8 +22,8 @@ public class OHLCPlugInView extends ViewSupport { private final AgentInstanceViewFactoryChainContext context; private final ExprNode timestampExpression; private final ExprNode valueExpression; - private DurationWindow window; - private EventAdapterService service; + private CandlestickWindow window; + private EventAdapterService service; private EventBean[] lastData; @@ -42,8 +42,8 @@ public class OHLCPlugInView extends ViewSupport { this.valueExpression = valueExpression; service = context.getStatementContext().getEventAdapterService(); - window = new DurationWindow(this, calc, context, intervalExpression); CandlestickCalc calc = chooseCalc(calcTypeExpression); + window = chooseWindow(context, timeTypeExpression, intervalExpression, calc); } /** @@ -62,6 +62,27 @@ public class OHLCPlugInView extends ViewSupport { return new OHLCCandlestickCalc(); } + /** + * Return the proper window according to the value of the + * calc type parameter. + * @param intervalExpression + */ + private CandlestickWindow chooseWindow(AgentInstanceViewFactoryChainContext context, + ExprNode timeTypeExpression, + ExprNode intervalExpression, + CandlestickCalc calc) + { + String timeType = exprNodeValue(timeTypeExpression); + + if (CandlestickWindow.Type.valueOf(timeType) == CandlestickWindow.Type.time) { + log.info("Using time based window type"); + return new TimeCandlestickWindow(this, calc, context, intervalExpression); + } + + log.info("Using ticks based window type"); + return new TicksCandlestickWindow(this, calc, context, intervalExpression); + } + /** * Return the string value of a node. */ diff --git a/src/main/java/ats/plugin/TicksCandlestickWindow.java b/src/main/java/ats/plugin/TicksCandlestickWindow.java new file mode 100644 index 0000000..d2f603c --- /dev/null +++ b/src/main/java/ats/plugin/TicksCandlestickWindow.java @@ -0,0 +1,87 @@ +package ats.plugin; + +import com.espertech.esper.core.context.util.AgentInstanceViewFactoryChainContext; +import com.espertech.esper.epl.expression.core.ExprEvaluator; +import com.espertech.esper.epl.expression.core.ExprNode; + +import org.joda.time.DateTime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * TicksCandlestickWindow runs a CandlestickCalc across a set number + * of ticks for each window. + */ +class TicksCandlestickWindow implements CandlestickWindow { + private static final Logger log = LoggerFactory.getLogger(TicksCandlestickWindow.class); + private final AgentInstanceViewFactoryChainContext context; + /** How many ticks in each window? */ + private final long windowTicks; + private OHLCPlugInView plugin; + private CandlestickCalc calc; + /** How many ticks into the window we are. */ + private long currentTick = 0; + /** The time the window started. */ + private DateTime windowStartTime; + + + /** + * Create a new window that calculates across a set number of + * ticks. + */ + public TicksCandlestickWindow(OHLCPlugInView plugin, + CandlestickCalc calc, + AgentInstanceViewFactoryChainContext context, + ExprNode intervalExpression) + { + this.plugin = plugin; + this.calc = calc; + this.context = context; + windowTicks = parseTickCount(intervalExpression); + } + + /** + * Return the time period specified by the given expression value. + */ + private long parseTickCount(ExprNode intervalExpression) { + ExprEvaluator evaluator = intervalExpression.getForge().getExprEvaluator(); + Object o = evaluator.evaluate(null, true, context); + log.warn("OBJECT " + o.getClass()); + return new Long((Integer)o).longValue(); + } + + /** + * Process a tick with the given time and value. + */ + public void update(DateTime timestamp, double value) { + ensureWindow(timestamp); + calc.applyValue(value); + } + + /** + * Make sure our window times are set up and current. + * @param timestamp + */ + public void ensureWindow(DateTime timestamp) { + if (windowStartTime == null) + windowStartTime = timestamp; + + currentTick++; + log.info("tick ", currentTick); + + if (currentTick < windowTicks) return; + + OHLCValues values = calc.getValues(); + if (values == null) { + log.info("No data to post"); + return; + } + + plugin.postEvent(new OHLCEvent(windowStartTime, values)); + + // reset for next window + calc.reset(); + currentTick = 0; + windowStartTime = null; + } +} diff --git a/src/main/java/ats/plugin/DurationWindow.java b/src/main/java/ats/plugin/TimeCandlestickWindow.java similarity index 91% rename from src/main/java/ats/plugin/DurationWindow.java rename to src/main/java/ats/plugin/TimeCandlestickWindow.java index 523b241..23ef0e8 100644 --- a/src/main/java/ats/plugin/DurationWindow.java +++ b/src/main/java/ats/plugin/TimeCandlestickWindow.java @@ -17,10 +17,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * DurationWindow TODO + * TimeCandlestickWindow runs a CandlestickCalc across ticks for a set + * duration each window. */ -class DurationWindow { - private static final Logger log = LoggerFactory.getLogger(DurationWindow.class); +class TimeCandlestickWindow implements CandlestickWindow { + private static final Logger log = LoggerFactory.getLogger(TimeCandlestickWindow.class); private static final int LATE_EVENT_SLACK_SECONDS = 5; private static final PeriodFormatter periodFormatter = new PeriodFormatterBuilder() .appendDays().appendSuffix("d") @@ -39,10 +40,13 @@ class DurationWindow { private DateTime lastStartTime; - public DurationWindow(OHLCPlugInView plugin, - CandlestickCalc calc, - AgentInstanceViewFactoryChainContext context, - ExprNode intervalExpression) + /** + * Create a window over the given duration. + */ + public TimeCandlestickWindow(OHLCPlugInView plugin, + CandlestickCalc calc, + AgentInstanceViewFactoryChainContext context, + ExprNode intervalExpression) { this.plugin = plugin; this.calc = calc; @@ -161,7 +165,7 @@ class DurationWindow { public void scheduledTrigger(EngineLevelExtensionServicesContext esc) { handle = null; // clear out schedule handle // log.info("Callback running"); - DurationWindow.this.postData(); + TimeCandlestickWindow.this.postData(); } };