Add configurable candlestick window types

This commit is contained in:
2018-11-02 12:01:29 -07:00
parent d1225c27d1
commit cc9f25c6b2
4 changed files with 140 additions and 11 deletions

View File

@ -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);
}

View File

@ -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.
*/

View File

@ -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;
}
}

View File

@ -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();
}
};