Complete Predictor Code

#include "include/xmim_cfunc_api.h"
#include <stdio.h>

//names for the input parameters
#define PRED_STOCK1 "stock1"
#define PRED_STOCK2 "stock2"
//names for the state parameters
#define PRED_TIME_SERIES "time_series"
#define PRED_RESULT "result"

//column to use when creating a time
//series for the stock symbols
#define DEFAULT_COLUMN "Asks"

//struct to store in the state
  typedef struct {
    double *values;
    xmim_cfunc_date_time **dates;
    int size;
  } pred_result;

//specify the input parameters and the state
extern "C" int cfunc_instance_init_defaults (xmim_cfunc_args *args) {
  int num = 2;
  //security args
  xmim_cfunc_security_args *sec = new xmim_cfunc_security_args;
  sec->size = num;
  sec->names = new char*[num];
  sec->names[0] = PRED_STOCK1;
  sec->names[1] = PRED_STOCK2;
  sec->rels = new char*[num];
  sec->rels[0] = NULL;
  sec->rels[1] = NULL;

  args->security_args = sec;

  xmim_cfunc_state *state = new xmim_cfunc_state;
  num = 2;
  state->size = num;
  state->ptr = new xmim_cfunc_obj_ptr[num];
  for (int i = 0; i < num; i++)
    state->ptr[i].obj = NULL;

  state->names = new char*[num];
  state->names[0] = PRED_TIME_SERIES;
  state->names[1] = PRED_RESULT;

  args->state = state;

  return 1;
}

//initialize the state
extern "C" int cfunc_instance_init (xmim_cfunc_args *args) {  
  char *relname1 = NULL, *relname2 = NULL;
  void *series1 = NULL, *series2 = NULL;
  xmim_cfunc_date_time *from_date = NULL, *to_date = NULL, *date = NULL, *old_date = NULL;
  void *offset;
  pred_result *result = NULL;
  int size = 0;

  //first input argument
  relname1 = (char *)xmim_cfunc_get_arg (args, P_SECURITY, PRED_STOCK1);
  if (!relname1)
    return 0;

  //second input argument
  relname2 = (char *)xmim_cfunc_get_arg (args, P_SECURITY, PRED_STOCK2);
  if (!relname2)
    return 0;

  //create the time series for the first stock symbol
  series1 = xmim_cfunc_get_time_series (args, relname1, DEFAULT_COLUMN);
  if (!series1)
    return 0;
  //store the first time series in the state
  if (!xmim_cfunc_set_arg (args, P_STATE, series1, PRED_TIME_SERIES))
    return 0;

  //create the time series for the second stock symbol  
  //will get deleted in the ~CoCompiler () [CoCompiler::deleteExObjects]
  series2 = xmim_cfunc_get_time_series (args, relname2, DEFAULT_COLUMN);  
  if (!series2)
    return 0;

  // the from and to dates for the first time series
  // the date range we are going to use
  from_date = xmim_cfunc_get_from_date (args, series1);
  to_date = xmim_cfunc_get_to_date (args, series1);

  //calculate the number of values we have
  date = xmim_cfunc_get_from_date (args, series1);
  size = 1;

  while (!xmim_cfunc_date_time_equal (args, date, to_date)) {
    offset = xmim_cfunc_get_time_offset (args, 1, PL_DAYS, PL_LATER);
    old_date = date;
    date = xmim_cfunc_apply_time_offset (args, date, series1, offset);
    xmim_cfunc_free_date_time (args, old_date);
    xmim_cfunc_free_time_offset (args, offset);  
    size++;
  }

  //compute the result
  result = new pred_result;
  result->values = new double[size];
  result->dates = new xmim_cfunc_date_time*[size];
  result->size = size;
  
  double v1, v2, prev_v1, prev_v2;
  //the first value is a NaN since we do not have the 
  //value on the previous date
  double zero = 0;
  double *doubleNan = &zero;
  xmim_cfunc_makeNan (args, doubleNan);
  result->values[0] = *doubleNan;
  result->dates[0] = from_date;  
  prev_v1 = xmim_cfunc_get_value (args, series1, from_date);
  prev_v2 = xmim_cfunc_get_value (args, series2, from_date);
  //compute the values using the two time series
  for (int i = 1; i < size; i++) {
    offset = xmim_cfunc_get_time_offset (args, i, PL_DAYS, PL_LATER);
    date = xmim_cfunc_apply_time_offset (args, from_date, series1, offset);
    v1 = xmim_cfunc_get_value (args, series1, date);
    v2 = xmim_cfunc_get_value (args, series2, date);
    result->values[i] = v1 + 
      (0.5 * v1 * 
      (((v1 - prev_v1) / prev_v1) + 
      ((v2 - prev_v2) / prev_v2)));
        
    result->dates[i] = date;
    prev_v1 = v1;
    prev_v2 = v2;
    xmim_cfunc_free_time_offset (args, offset);  
  }

  
  //store the result in the state
  if (!xmim_cfunc_set_arg (args, P_STATE, result, PRED_RESULT))
    return 0;

  return 1;
}

extern "C" int cfunc_instance_compute_trading_pattern (xmim_cfunc_args *args) {
  void *time_series = xmim_cfunc_get_arg (args, P_STATE, PRED_TIME_SERIES);

  if (!time_series)
    return 0;

  xmim_cfunc_compute_trading_pattern (args, time_series);
  
  return 1;
}

extern "C" int cfunc_instance_compute_trading_date_range (xmim_cfunc_args *args) {
  void *time_series = xmim_cfunc_get_arg (args, P_STATE, PRED_TIME_SERIES);

  if (!time_series)
    return 0;

  xmim_cfunc_compute_trading_date_range (args, time_series);
  
  return 1;  
}

extern "C" int cfunc_instance_get_value (xmim_cfunc_args *args, xmim_cfunc_date_time *dt) {
  pred_result *result = (pred_result *)xmim_cfunc_get_arg (args, P_STATE, PRED_RESULT);
  xmim_cfunc_date_time *date = NULL;

  if (!result)
    return 0;

  for (int i = 0; i < result->size; i++) {
    date = (xmim_cfunc_date_time *) result->dates[i];
    if (xmim_cfunc_date_time_equal (args, date, dt)) {
      args->result = result->values[i];
      return 1;
    }
  }
  //we do not have the requested date - return NaN.
  double zero = 0;
  double *doubleNan = &zero;
  xmim_cfunc_makeNan (args, doubleNan);
  args->result = *doubleNan;

  return 1;
}

extern "C" int cfunc_instance_destroy (xmim_cfunc_args *args) {
  delete[] args->security_args->rels;
  delete[] args->security_args->names;
  delete args->security_args;  
  args->security_args = NULL;
  
  //the RelCol object pointed to by args->state->ptr[0].obj  
  //has already been deleted for us
  //in the ~CoCompiler () [CoCompiler::deleteExObjects]  

  pred_result *result = (pred_result *)xmim_cfunc_get_arg (args, P_STATE, PRED_RESULT);
  if (result) {
    for (int i = 0; i < result->size; i++)
      delete result->dates[i];

    delete[] result->dates;
    delete[] result->values;

    delete result;
  }

  return 1;
}