コード例 #1
0
ファイル: ta_abstract.c プロジェクト: royratcliffe/ta-lib
   static TA_RetCode getGroupId( const char *groupString, unsigned int *groupId )
#endif
{
   #ifdef TA_GEN_CODE
   TA_PROLOG;
   #endif

   unsigned int i;

   #ifdef TA_GEN_CODE
      TA_TRACE_BEGIN( libHandle, getgroupId );

      TA_ASSERT( libHandle, groupString != NULL );
      TA_ASSERT( libHandle, groupId != NULL );
   #endif

   for( i=0; i < TA_NB_GROUP_ID; i++ )
   {
      if( strcmp( TA_GroupString[i], groupString ) == 0 )
      {
         *groupId = i;
         #ifdef TA_GEN_CODE
            TA_TRACE_RETURN( TA_SUCCESS );
         #else
            return TA_SUCCESS;
         #endif
      }
   }

   #ifdef TA_GEN_CODE
      TA_TRACE_RETURN( TA_GROUP_NOT_FOUND );
   #else
      return TA_GROUP_NOT_FOUND;
   #endif
}
コード例 #2
0
ファイル: ta_abstract.c プロジェクト: royratcliffe/ta-lib
   static TA_RetCode getFuncNameByIdx( TA_GroupId groupId,
                                       unsigned int idx,
                                       const char **stringPtr )
#endif
{
   #ifdef TA_GEN_CODE
      /* Code used only when compiled with gen_code. */
      TA_PROLOG;
      unsigned int curIdx;
      unsigned int i, j, found;
      const TA_FuncDef **funcDefTable;
      unsigned int tableSize;
      const TA_FuncInfo *funcInfo;

      TA_TRACE_BEGIN( libHandle, getFuncNameByIdx );

      TA_ASSERT( libHandle, stringPtr != NULL );

      curIdx = 0;
      found = 0;
      for( i=0; (i < 26) && !found; i++ )
      {
         funcDefTable = TA_DEF_Tables[i];
         tableSize = *(TA_DEF_TablesSize[i]);

         for( j=0; (j < tableSize) && !found; j++ )
         {
            if( funcDefTable[j]->groupId == groupId )
            {
               if( idx == curIdx )
               {
                  funcInfo = funcDefTable[j]->funcInfo;
                  TA_ASSERT( libHandle, funcInfo != NULL );
                  *stringPtr = funcInfo->name;
                  found = 1;
               }
               curIdx++;
            }
         }
      }

      TA_ASSERT( libHandle, found == 1 );
      TA_ASSERT( libHandle, *stringPtr != NULL );

      TA_TRACE_RETURN( TA_SUCCESS );
   #else
      /* Optimized code in the final library. */
      const TA_FuncDef **funcDefTable;
      const TA_FuncInfo *funcInfo;

      funcDefTable = TA_PerGroupFuncDef[groupId];
      funcInfo = funcDefTable[idx]->funcInfo;
      *stringPtr = funcInfo->name;

      return TA_SUCCESS;
   #endif
}
コード例 #3
0
ファイル: ta_cc_abcd.cpp プロジェクト: evaleev/tiledarray
TA::detail::DistEval<typename Op::result_type, Policy> make_contract_eval(
    const TA::detail::DistEval<LeftTile, Policy>& left,
    const TA::detail::DistEval<RightTile, Policy>& right, madness::World& world,
    const typename TA::detail::DistEval<typename Op::result_type,
                                        Policy>::shape_type& shape,
    const std::shared_ptr<typename TA::detail::DistEval<
        typename Op::result_type, Policy>::pmap_interface>& pmap,
    const TA::Permutation& perm, const Op& op) {
  TA_ASSERT(left.range().rank() == op.left_rank());
  TA_ASSERT(right.range().rank() == op.right_rank());
  TA_ASSERT((perm.dim() == op.result_rank()) || !perm);

  // Define the impl type
  typedef TA::detail::Summa<
      TA::detail::DistEval<LeftTile, Policy>,
      TA::detail::DistEval<RightTile, Policy>, Op, Policy> impl_type;

  // Precompute iteration range data
  const unsigned int num_contract_ranks = op.num_contract_ranks();
  const unsigned int left_end = op.left_rank();
  const unsigned int left_middle = left_end - num_contract_ranks;
  const unsigned int right_end = op.right_rank();

  // Construct a vector TiledRange1 objects from the left- and right-hand
  // arguments that will be used to construct the result TiledRange. Also,
  // compute the fused outer dimension sizes, number of tiles and elements,
  // for the contraction.
  typename impl_type::trange_type::Ranges ranges(op.result_rank());
  std::size_t M = 1ul, m = 1ul, N = 1ul, n = 1ul;
  std::size_t pi = 0ul;
  for(unsigned int i = 0ul; i < left_middle; ++i) {
    ranges[(perm ? perm[pi++] : pi++)] = left.trange().data()[i];
    M *= left.range().extent(i);
    m *= left.trange().elements_range().extent(i);
  }
  for(std::size_t i = num_contract_ranks; i < right_end; ++i) {
    ranges[(perm ? perm[pi++] : pi++)] = right.trange().data()[i];
    N *= right.range().extent(i);
    n *= right.trange().elements_range().extent(i);
  }

  // Compute the number of tiles in the inner dimension.
  std::size_t K = 1ul;
  for(std::size_t i = left_middle; i < left_end; ++i)
    K *= left.range().extent(i);

  // Construct the result range
  typename impl_type::trange_type trange(ranges.begin(), ranges.end());

  // Construct the process grid
  TA::detail::ProcGrid proc_grid(world, M, N, m, n);

  return TA::detail::DistEval<typename Op::result_type, Policy>(
      std::shared_ptr<impl_type>( new impl_type(left, right, world, trange,
      shape, pmap, perm, op, K, proc_grid)));
}
コード例 #4
0
TA_RetCode TA_FileSeqClose( TA_FileHandle *handle )
{
   TA_PROLOG
   TA_RetCode retCode;
   TA_FileHandlePriv *fileHandlePriv;
   TA_SystemGlobal *global;
   #if defined( USE_WIN32_API )
   DWORD win32Error;
   BOOL retValue;
   #endif

   TA_TRACE_BEGIN(  TA_FileSeqClose );

   retCode = TA_GetGlobal(  &TA_SystemGlobalControl, (void **)&global );
   if( retCode != TA_SUCCESS )
   {
      TA_TRACE_RETURN( retCode );
   }

   TA_ASSERT( handle != NULL );

   fileHandlePriv = (TA_FileHandlePriv *)handle;

   if( fileHandlePriv )
   {
      #if defined( USE_WIN32_API )
         if( fileHandlePriv->handle != INVALID_HANDLE_VALUE )
         {
            retValue = CloseHandle( fileHandlePriv->handle );
            if( retValue == 0 )
            {
               win32Error = GetLastError();
               global->lastError = win32Error;
               TA_FATAL(  NULL, 0, win32Error );
            }
         }
         if( fileHandlePriv->allocBuffer )
         {
            freeDiskBuffer( fileHandlePriv->allocBuffer,
                            fileHandlePriv->allocBufferSize );
         }
      #endif

      #if defined( USE_OSLAYER )
         if( fileHandlePriv->handle != NULL )
            fclose( fileHandlePriv->handle );
         if( fileHandlePriv->allocBuffer )
            TA_Free(  fileHandlePriv->allocBuffer );
      #endif

      if( fileHandlePriv->streamAccess )
      {
         TA_StreamAccessFree( fileHandlePriv->streamAccess );
      }

      TA_Free(  fileHandlePriv );
   }

   TA_TRACE_RETURN( TA_SUCCESS );
}
コード例 #5
0
/* Allows to dynamically add a mini-driver. */
TA_RetCode TA_SQL_AddMinidriver( const char scheme[], const TA_SQL_Minidriver *minidriver )
{
   TA_PROLOG
   TA_String *schemeStr;
   TA_StringCache *cache;

   TA_RetCode retCode;

   TA_TRACE_BEGIN( TA_SQL_AddMinidriver );

   if( !minidriverDict )
   {
      minidriverDict = TA_DictAlloc( TA_DICT_KEY_ONE_STRING, NULL );
      if( !minidriverDict )
      {
         TA_TRACE_RETURN( TA_ALLOC_ERR );
      }
   }

   cache = TA_GetGlobalStringCache();
   TA_ASSERT( cache != NULL );
   schemeStr = TA_StringAlloc( cache, scheme );
   if( !schemeStr )
   {
      TA_DictFree(minidriverDict);
      TA_TRACE_RETURN( TA_ALLOC_ERR );
   }

   retCode = TA_DictAddPair_S( minidriverDict, schemeStr, (void *)minidriver );
   TA_StringFree( cache, schemeStr );

   TA_TRACE_RETURN( retCode );
}
コード例 #6
0
ファイル: ta_abstract.c プロジェクト: royratcliffe/ta-lib
   static TA_RetCode getGroupSize( TA_GroupId groupId, unsigned int *groupSize )
#endif
{
   #ifdef TA_GEN_CODE
      /* Code used only when compiled with gen_code. */
      TA_PROLOG;
      unsigned int i, j;
      const TA_FuncDef **funcDefTable;
      const TA_FuncDef *funcDef;
      unsigned int tableSize;
      unsigned int nbFuncFound;

      TA_TRACE_BEGIN( libHandle, getGroupSize );

      TA_ASSERT( libHandle, groupId < TA_NB_GROUP_ID );

      TA_ASSERT( libHandle, groupId < TA_NB_GROUP_ID );
      TA_ASSERT( libHandle, groupSize != NULL );

      nbFuncFound = 0;
      for( i=0; i < 26; i++ )
      {
         funcDefTable = TA_DEF_Tables[i];
         tableSize = *(TA_DEF_TablesSize[i]);

         for( j=0; j < tableSize; j++ )
         {
            funcDef = funcDefTable[j];
            if( funcDef && (funcDef->groupId == groupId) )
               nbFuncFound++;
         }
      }

      *groupSize = nbFuncFound;

      TA_TRACE_RETURN( TA_SUCCESS );
   #else
      /* Optimized code in the final library. */
      *groupSize = TA_PerGroupSize[groupId];

      return TA_SUCCESS;
   #endif
}
コード例 #7
0
ファイル: ta_historycheck.c プロジェクト: royratcliffe/ta-lib
/**** Global functions definitions.   ****/
TA_RetCode TA_HistoryCheckInternal( TA_Libc            *libHandle,
                                    TA_Period           expectedPeriod,
                                    const TA_Timestamp *expectedStart,
                                    const TA_Timestamp *expectedEnd,
                                    TA_Field            fieldToCheck,
                                    const TA_History   *history,
                                    unsigned int       *faultyIndex,
                                    unsigned int       *faultyField )
{
   TA_PROLOG;
   unsigned int allFieldNull;

   (void)faultyField;
   (void)faultyIndex;
   (void)fieldToCheck;
   (void)expectedEnd;
   (void)expectedStart;

   TA_TRACE_BEGIN( libHandle, TA_HistoryCheckInternal );

   TA_ASSERT( libHandle, history != NULL );

   /* Period shall be always set in the history. */
   if( history->period != expectedPeriod )
   {
      TA_TRACE_RETURN( TA_UNKNOWN_ERR );
   }

   /* Verify that an empty history is really empty. */
   if( (history->open  == NULL) &&
       (history->high  == NULL) &&
       (history->low   == NULL) &&
       (history->close == NULL) &&
       (history->volume == NULL) &&
       (history->openInterest == NULL) &&
       (history->timestamp == NULL) )
   {
      allFieldNull = 1;
      if( history->nbBars != 0 )
      {
         TA_TRACE_RETURN( TA_UNKNOWN_ERR );
      }
   }
   else
      allFieldNull = 0;

   if( (history->nbBars == 0) && !allFieldNull )
   {
      TA_TRACE_RETURN( TA_UNKNOWN_ERR );
   }

   /* !!! Some more runtime verification could be added here... */

   TA_TRACE_RETURN( TA_SUCCESS );
}
コード例 #8
0
ファイル: SQLCode.cpp プロジェクト: shenglonglin2000/MT
void  SQLCode::_GetSQLFormat(const std::string& strSQLKey, SQLStatement& strSQLFormats)
{
	ThreadGuard guard(m_threadLock); // avoid threads racing
	TA_ASSERT(NULL != m_pSqlFileHelper, "sql file helper handler is null.");
	m_pSqlFileHelper->getSQLString(strSQLKey, strSQLFormats);

	if (strSQLFormats.strCommon.empty() && strSQLFormats.strMySQL.empty() && strSQLFormats.strSqlite.empty())
	{
		TA_THROW(BadParamCount("Cannot find the SQL statement in the hash-table"));	
	}
}
コード例 #9
0
/* Like TA_FileSeqOpen, but work with a stream instead. */
TA_RetCode TA_FileSeqOpenFromStream( TA_Stream *stream,
                                     TA_FileHandle **handle )
{
   TA_PROLOG
   TA_FileHandlePriv *fileHandlePriv;

   TA_TRACE_BEGIN(  TA_FileSeqOpen );

   TA_ASSERT( stream != NULL );
   TA_ASSERT( handle != NULL );

   /* Allocate the private file handle. */
   fileHandlePriv = (TA_FileHandlePriv *)TA_Malloc( sizeof( TA_FileHandlePriv ) );
   if( !fileHandlePriv )
   {
      TA_TRACE_RETURN( TA_ALLOC_ERR );
   }
   memset( fileHandlePriv, 0, sizeof( TA_FileHandlePriv ) );

   /* There is NO file... */
   #if defined( USE_WIN32_API )
   fileHandlePriv->handle = INVALID_HANDLE_VALUE; 
   #endif

   #if defined( USE_OSLAYER )
   fileHandlePriv->handle = (FILE *)NULL;
   #endif

   /* ... use a stream instead. */
   fileHandlePriv->stream = stream;
   fileHandlePriv->streamAccess = TA_StreamAccessAlloc( stream );
   if( !fileHandlePriv->streamAccess )
   {
      TA_TRACE_RETURN( TA_ALLOC_ERR );
   }

   /* Success! Return the info to the caller. */
   *handle = (TA_FileHandle *)fileHandlePriv;
   TA_TRACE_RETURN( TA_SUCCESS );
}
コード例 #10
0
ファイル: ta_cc_abcd.cpp プロジェクト: evaleev/tiledarray
// makes tiles of fluctuating sizes
// if n = average tile size
// this will produce tiles of these sizes: n+1, n-1, n+2, n-2, etc.
// the last tile absorbs the remainder
std::vector<unsigned int>
make_tiling(unsigned int range_size,
            unsigned int ntiles) {
  const auto average_tile_size = range_size / ntiles;
  TA_ASSERT(average_tile_size > ntiles);
  std::vector<unsigned int> result(ntiles+1);
  result[0] = 0;
  for(long t=0; t!=ntiles-1; ++t) {
    result[t+1] = result[t] + average_tile_size + ((t%2==0)?(t+1):(-t));
  }
  result[ntiles] = range_size;
  return result;
}
コード例 #11
0
static TA_RetCode TA_SystemGlobalShutdown( void *globalAllocated )
{
   TA_PROLOG
   TA_RetCode retCode, finalRetCode;
   TA_SystemGlobal *global;

   TA_TRACE_BEGIN( TA_SystemGlobalShutdown );

   /* No need to shutdown if the initialization failed. */
   if( globalAllocated == NULL )
   {
      TA_TRACE_RETURN( TA_SUCCESS );
   }

   finalRetCode = TA_SUCCESS;

   global = (TA_SystemGlobal *)globalAllocated;

   if( global->dirnameCache )
   {
      retCode = TA_StringCacheFree( global->dirnameCache );
      TA_ASSERT( retCode == TA_SUCCESS );
      if( retCode != TA_SUCCESS )
         finalRetCode = retCode;
   }

   if( global->filenameCache )
   {
      retCode = TA_StringCacheFree( global->filenameCache );
      TA_ASSERT( retCode == TA_SUCCESS );
      if( retCode != TA_SUCCESS )
         finalRetCode = retCode;
   }

   TA_Free(  global );

   TA_TRACE_RETURN( finalRetCode );
}
コード例 #12
0
TA_RetCode TA_FileIndexAddTreeValue( TA_FileIndexPriv *data,
                                     TA_String *string,
                                     TA_ValueTreeNode **added )
{
   TA_PROLOG;
   TA_ValueTreeNode *node;
   unsigned int allocateEmptyString;
   TA_Libc *libHandle;
   TA_StringCache *stringCache;

   libHandle = data->libHandle;
   TA_TRACE_BEGIN( libHandle, TA_FileIndexAddTreeValue );

   stringCache = TA_GetGlobalStringCache( libHandle );

   allocateEmptyString = 0;
   TA_ASSERT( libHandle, data != NULL );

   if( added )
      *added = NULL;

   if( !string )
   {
      string = TA_StringAlloc( stringCache, "" );
      if( !string )
      {
         TA_TRACE_RETURN( TA_ALLOC_ERR );
      }
      allocateEmptyString = 1;
   }

   /* Alloc the TA_ValueTreeNode */
   node = allocTreeNode( libHandle, data->currentNode, string );

   if( allocateEmptyString )
      TA_StringFree( stringCache, string );

   if( !node )
   {
      TA_TRACE_RETURN( TA_ALLOC_ERR );
   }

   data->currentNode = node;

   if( added )
      *added = node;

   TA_TRACE_RETURN( TA_SUCCESS );
}
コード例 #13
0
static TA_RetCode TA_SystemGlobalInit( void **globalToAlloc )
{
   TA_PROLOG
   TA_RetCode retCode;
   TA_SystemGlobal *global;

   TA_TRACE_BEGIN( TA_SystemGlobalInit );

   TA_ASSERT( globalToAlloc != NULL );

   *globalToAlloc = NULL;

   global = (TA_SystemGlobal *)TA_Malloc( sizeof( TA_SystemGlobal ) );
   if( !global )
   {
      TA_TRACE_RETURN( TA_ALLOC_ERR );
   }

   memset( global, 0, sizeof( TA_SystemGlobal ) );

   retCode = TA_StringCacheAlloc( &global->dirnameCache );
   if( retCode != TA_SUCCESS )
   {
      TA_Free( global );
      TA_TRACE_RETURN( TA_ALLOC_ERR );
   }

   retCode = TA_StringCacheAlloc( &global->filenameCache );
   if( retCode != TA_SUCCESS )
   {
      TA_StringCacheFree( global->dirnameCache );
      TA_Free( global );
      TA_TRACE_RETURN( TA_ALLOC_ERR );
   }

   /* Success! Return the global to the caller. */
   *globalToAlloc = global;
   TA_TRACE_RETURN( TA_SUCCESS );
}
コード例 #14
0
TA_RetCode TA_FileIndexFreeValueTree( TA_Libc *libHandle,
                                      TA_ValueTreeNode *fromNode )
{
   TA_PROLOG;
   TA_RetCode retCode;
   TA_ValueTreeNode *tmp;
   TA_StringCache *stringCache;

   TA_TRACE_BEGIN( libHandle, TA_FileIndexFreeValueTree );

   TA_ASSERT( libHandle, fromNode != NULL );

   stringCache = TA_GetGlobalStringCache( libHandle );

   /* Remove itself from parent->child list if parent still around. */
   if( fromNode->parent )
   {
      tmp = ((TA_ValueTreeNode *)fromNode->parent);
      if( tmp->child )
         TA_ListRemoveEntry( tmp->child, (void *)fromNode );
   }

   if( fromNode->string )
      TA_StringFree( stringCache, fromNode->string );

   /* Deletes all childs. */
   if( fromNode->child )
   {
      retCode = freeListAndElement( libHandle, fromNode->child, freeTreeNode );
      if( retCode != TA_SUCCESS )
         TA_TRACE_RETURN( retCode );
   }

   TA_Free( libHandle, fromNode );

   TA_TRACE_RETURN( TA_SUCCESS );
}
コード例 #15
0
TA_RetCode TA_ReadOp_Do( TA_FileHandle       *fileHandle,
                         const TA_ReadOpInfo *readOpInfo,
                         TA_Period            period,
                         const TA_Timestamp  *start,
                         const TA_Timestamp  *end,
                         unsigned int         minimumNbBar,
                         TA_Field             fieldToAlloc,
                         TA_ParamForAddData  *paramForAddData,
                         unsigned int        *nbBarAdded )
{
   TA_PROLOG
   TA_RetCode retCode;
   TA_EstimateInfo estimationInfo;

   unsigned int nbElementToAllocate;
   unsigned int memoryNeeded; /* Boolean */
   unsigned int timeNeeded;   /* Boolean */

   TA_Real    *arrayReal[TA_REAL_ARRAY_SIZE];
   TA_Integer *arrayInteger[TA_INTEGER_ARRAY_SIZE];
   TA_Timestamp *timestamp;

   TA_Real *openBeg, *highBeg, *lowBeg, *closeBeg;
   TA_Integer *volumeBeg, *openInterestBeg;
   TA_Timestamp *timestampBeg;
   TA_Timestamp tmpTimestamp;

   TA_ReadOp op;

   TA_Field fieldToProcess;
   unsigned int year, month, day, hour, min, sec;
   TA_Integer curOp;

   unsigned int nbTotalByteDone, nbTotalBarDone;
   unsigned int nbBarAddedInTheBlock;

   char monthChar[4];
   char cnvtArray[CNVT_ARRAY_SIZE];
   unsigned int  cnvtArrayIdx;

   unsigned int nbByteToAllocReal;
   unsigned int nbByteToAllocInteger;

   unsigned int fileSize;
   unsigned int skipField;
   unsigned int lineToSkip;

   unsigned int nbByteRead;
   unsigned int nbLetter;

   TA_Real lastValidClose;

   const char *car;

   register TA_Real tmpReal;
   register TA_Integer tmpInt;
   register unsigned int tmpIdx;
   register unsigned int nbCharToRead;

   unsigned int lastOpFieldIncremented;
   TA_TRACE_BEGIN( TA_PriceBarRead );

   /* Initialization of local variables. */
   openBeg = highBeg = lowBeg = closeBeg = NULL;
   timestampBeg = NULL;
   volumeBeg = openInterestBeg = NULL;
   timestamp = NULL;
   retCode = TA_SUCCESS;
   lastValidClose = 0.0;

   fieldToProcess = readOpInfo->fieldProvided & fieldToAlloc;
   if( (fieldToProcess & fieldToAlloc) != fieldToAlloc )
   {
      /* Nothing to read because not all the requested
       * fields are provided by this data source!
       */
      return TA_SUCCESS;
   }

   /* Estimate the initial amount of memory to allocate. */
   fileSize = TA_FileSize( fileHandle );
   retCode = TA_EstimateAllocInit( start, end, period,                                   
                                   minimumNbBar, 2048,
                                   &estimationInfo,
                                   &nbElementToAllocate );
   if( retCode != TA_SUCCESS )
   {
      TA_TRACE_RETURN( retCode );
   }

   if( nbElementToAllocate == 0 )
   {
      TA_TRACE_RETURN( TA_SUCCESS ); /* Nothing to read!? Just return... */
   }

   memset( arrayInteger, 0, sizeof( arrayInteger ) );
   memset( arrayReal,    0, sizeof( arrayReal ) );

   /* Set the date/time pointers to where the information will be stored. */
   arrayInteger[TA_HOUR_IDX]  = (TA_Integer *)&hour;
   arrayInteger[TA_MIN_IDX]   = (TA_Integer *)&min;
   arrayInteger[TA_SEC_IDX]   = (TA_Integer *)&sec;
   arrayInteger[TA_MONTH_IDX] = (TA_Integer *)&month;
   arrayInteger[TA_YEAR_IDX]  = (TA_Integer *)&year;
   arrayInteger[TA_DAY_IDX]   = (TA_Integer *)&day;

   /* Set default time/date. */
   year  = 1900;
   month = day = 1;
   hour  = 23;
   min   = sec = 59;

   /* Check if the processing of the time will be needed. */
   timeNeeded = isTimeNeeded( readOpInfo->arrayReadOp);

   /* 'car' always point to the character being currently handled. */
   nbByteRead = 0;
   car = TA_FileSeqRead( fileHandle, &nbByteRead );
   if( (car == NULL) || (nbByteRead == 0) )
      return TA_SUCCESS; /* End of file! */
   --nbByteRead;

   nbTotalByteDone = 0;
   nbTotalBarDone  = 0;
   nbBarAddedInTheBlock = 0;
   memoryNeeded    = 1;
   curOp           = 0;
   skipField       = 0;

   monthChar[3] = '\0';

   /* When requested, skip header lines. */
   lineToSkip = readOpInfo->nbHeaderLineToSkip;
   while( lineToSkip-- )
   {
      while( *car != '\n' )
      {
         GET_CHAR;
         if( car == NULL )
            goto exit_loops;
      }
   }

line_loop: /* Always jump here when end-of-line is found (EOL). */

      /* If curOp != 0, the last operations are canceled. */
      REVERT_OPERATIONS;
      curOp = 0;
      lastOpFieldIncremented = 0;

      /* Start over a new line. */

      if( memoryNeeded )
      {
         /* Allocate the memory. */
         nbByteToAllocReal = nbElementToAllocate * sizeof( TA_Real );
         nbByteToAllocInteger = nbElementToAllocate * sizeof( TA_Integer );

         timestamp = (TA_Timestamp *)TA_Malloc( nbElementToAllocate * sizeof( TA_Timestamp ) );
         timestampBeg = timestamp;

         if( !timestampBeg )
         {
            retCode = TA_ALLOC_ERR;
            goto exit_loops;
         }

         #define TA_ALLOC_MEM(upperc,lowerc,typepar) \
         { \
            if( fieldToProcess & TA_##upperc ) \
            { \
               lowerc##Beg = (TA_##typepar *)TA_Malloc( nbByteToAlloc##typepar ); \
               array##typepar[TA_##upperc##_IDX] = lowerc##Beg; \
               if( !lowerc##Beg ) \
               { \
                  retCode = TA_ALLOC_ERR; \
                  goto exit_loops; \
               } \
            } \
         }
         TA_ALLOC_MEM( OPEN,  open,  Real );
         TA_ALLOC_MEM( HIGH,  high,  Real );
         TA_ALLOC_MEM( LOW,   low,   Real );
         TA_ALLOC_MEM( CLOSE, close, Real );

         TA_ALLOC_MEM( VOLUME, volume, Integer );
         TA_ALLOC_MEM( OPENINTEREST, openInterest, Integer );
         #undef TA_ALLOC_MEM

         memoryNeeded = 0;
      }

op_loop: /* Jump here when ready to proceed with the next command. */

      op = readOpInfo->arrayReadOp[curOp];

      if( !(op&TA_CMD_READ_MONTH_CHAR) )
      {
         /* Skip leading non-numeric character. */
         SKIP_UNTIL_NUMERIC;
      }

      /* Shall we skip this field? */
      if( TA_IS_SKIP_SET(op) )
      {
         if( (op&(TA_CMD_READ_REAL|TA_CMD_READ_INTEGER)) == 0 )
         {
            tmpInt = TA_GET_NB_NUMERIC(op);
            curOp++;
            while( tmpInt-- )
            {
               GET_CHAR;
               CHECK_EOL_EOF;
            }
         }
         else
         {
            if( skipField == 0 )
            {
               skipField = TA_GET_NB_NUMERIC(op);
               TA_ASSERT( skipField > 0 );
            }

            if( --skipField == 0 )
               curOp++;

            SKIP_NUMERIC;
            if( (op&TA_CMD_READ_REAL) && (*car == '.') )
            {
               GET_CHAR;
               CHECK_EOL_EOF;
               SKIP_NUMERIC;
            }
         }
      }
      else
      {
         cnvtArrayIdx = 0;

         if( TA_IS_REAL_CMD(op) )
         {
            /* Extract a numeric into cnvtArray. */
            READ_IN_CNVT_ARRAY;

            /* This is a TA_Real. */
            if( car && (*car == '.') )
            {
               /* Read rest of the float after the '.' */
               READ_IN_CNVT_ARRAY;
            }
            cnvtArray[cnvtArrayIdx] = '\0';
            tmpReal = atof( &cnvtArray[0] );

            /* Write the TA_Real in memory. */
            tmpIdx = TA_GET_IDX(op);
            TA_ASSERT( tmpIdx < TA_REAL_ARRAY_SIZE );
            TA_ASSERT( arrayReal[tmpIdx] != NULL );
            if( tmpReal != 0.0 )
            {
               *(arrayReal[tmpIdx]) = tmpReal;
               if( tmpIdx == TA_CLOSE_IDX )
                  lastValidClose = tmpReal;
            }
            else if( TA_IS_REPLACE_ZERO(op) )
            {
               /* Replace this zero value with the last known close.
                * If there is no previous close, this line is ignored.
                */
               if( lastValidClose != 0.0 )
                  *(arrayReal[tmpIdx]) = lastValidClose;
               else
               {
                  SKIP_LINE;
               }
            }
            else
            {
               /* Zero are not expected, consider this as a failure
                * and ignore all further data from this file.
                */
               retCode = TA_PRICE_BAR_CONTAINS_ZERO;
               goto exit_loops;
            }

            arrayReal[tmpIdx]++;
            curOp++;
         }
         else
         {
            /* This is a TA_Integer. */
            if( !(op&TA_CMD_READ_MONTH_CHAR) )
            {
               nbCharToRead = TA_GET_NB_NUMERIC(op);
               if( nbCharToRead )
               {
                  READ_N_CHAR_IN_CNVT_ARRAY(nbCharToRead);
               }
               else
               {
                  READ_IN_CNVT_ARRAY;
               }

               cnvtArray[cnvtArrayIdx] = '\0';
               tmpInt = atoi( &cnvtArray[0] );
            }
            else
            {
               /* Try to find a 3 letters month string. 
                * Translate it to a [1..12] integer.
                */
               nbLetter = 1;
               do
               {
                  CHECK_EOL_EOF;
                  monthChar[nbLetter] = (char)toupper(*car);
                  GET_CHAR;
                  nbLetter++;
               } while( nbLetter != 3 );
               
               do
               {
                  CHECK_EOL_EOF;
                  monthChar[0] = monthChar[1];
                  monthChar[1] = monthChar[2];
                  monthChar[2] = (char)toupper(*car);
                  if( strncmp("JAN",monthChar,3) == 0 )
                     tmpInt = 1;
                  else if( strncmp("FEB",monthChar,3) == 0 )
                     tmpInt = 2;
                  else if( strncmp("MAR",monthChar,3) == 0 )
                     tmpInt = 3;
                  else if( strncmp("APR",monthChar,3) == 0 )
                     tmpInt = 4;
                  else if( strncmp("MAY",monthChar,3) == 0 )
                     tmpInt = 5;
                  else if( strncmp("JUN",monthChar,3) == 0 )
                     tmpInt = 6;
                  else if( strncmp("JUL",monthChar,3) == 0 )
                     tmpInt = 7;
                  else if( strncmp("AUG",monthChar,3) == 0 )
                     tmpInt = 8;
                  else if( strncmp("SEP",monthChar,3) == 0 )
                     tmpInt = 9;
                  else if( strncmp("OCT",monthChar,3) == 0 )
                     tmpInt = 10;
                  else if( strncmp("NOV",monthChar,3) == 0 )
                     tmpInt = 11;
                  else if( strncmp("DEC",monthChar,3) == 0 )
                     tmpInt = 12;
                  else
                     tmpInt = 0;

                  GET_CHAR;
               } while( tmpInt == 0 );
            }

            /* Write the TA_Integer in memory. */
            tmpIdx = TA_GET_IDX(op);
            TA_ASSERT( tmpIdx < TA_INTEGER_ARRAY_SIZE );
            TA_ASSERT( arrayInteger[tmpIdx] != NULL );
            *(arrayInteger[tmpIdx]) = tmpInt;

            if( tmpIdx > TA_YEAR_IDX )
               arrayInteger[tmpIdx]++;
            curOp++;

            if( TA_IS_TIMESTAMP_COMPLETE(op) )
            {
               /* Build the timestamp. */
               retCode = TA_SetDate( year, month, day, &tmpTimestamp );
               if( retCode != TA_SUCCESS )
                  goto exit_loops; /* Invalid date */

               if( !timeNeeded )
               {
                  /* Ignore time in comparison and use default to build the price bar. */
                  tmpTimestamp.time = 23595900; /* Default EOD time */
                  if( start && (tmpTimestamp.date < start->date) )
                  {
                     /* This price bar is not needed, jump to the next line. */
                     retCode = TA_SUCCESS;
                     SKIP_LINE;
                  }

                  if( end && (tmpTimestamp.date > end->date) )
                  {
                     /* This price bar is beyond the upper limit, just exit. */
                     goto exit_loops;
                  }
               }
               else
               {
                  retCode = TA_SetTime( hour, min, sec, &tmpTimestamp );
                  if( retCode != TA_SUCCESS )
                     goto exit_loops; /* Invalid time */
                  if( start && TA_TimestampLess(&tmpTimestamp,start) )
                  {
                     /* This price bar is not needed, jump to the next line. */
                     retCode = TA_SUCCESS;
                     SKIP_LINE;
                  }

                  if( end && TA_TimestampGreater(&tmpTimestamp, end) )
                  {
                     /* This price bar is beyond the upper limit, just exit. */
                     goto exit_loops;
                  }
               }

               /* Write the timestamp in memory. */
               *timestamp = tmpTimestamp;
            }
         }

         if( TA_IS_READ_STOP_FLAG_SET(op) )
         {
            #ifdef DEBUG_PRINTF
               printf( "(%d%d%d,%e,%e,%e,%e,%d)\n",
                  timestampBeg?TA_GetYear(&timestampBeg[nbBarAddedInTheBlock]):0,
                  timestampBeg?TA_GetMonth(&timestampBeg[nbBarAddedInTheBlock]):0,
                  timestampBeg?TA_GetDay(&timestampBeg[nbBarAddedInTheBlock]):0,
                  openBeg?openBeg[nbBarAddedInTheBlock]:0.0,
                  highBeg?highBeg[nbBarAddedInTheBlock]:0.0,
                  lowBeg?lowBeg[nbBarAddedInTheBlock]:0.0,
                  closeBeg?closeBeg[nbBarAddedInTheBlock]:0.0,
                  volumeBeg?volumeBeg[nbBarAddedInTheBlock]:0 );
            #endif

            /* At this point, the price bar is completely written in memory. */
            timestamp++;
            curOp = 0;
            nbBarAddedInTheBlock++;
            if( nbBarAddedInTheBlock < nbElementToAllocate )
            {
              /* Go to next line. */
              SKIP_LINE;
            }
            else
            {
               /* There is not enough memory for another bar, so re-allocate
                * some more.
                */
               retCode = TA_HistoryAddData( paramForAddData, nbBarAddedInTheBlock,
                                            period, timestampBeg,
                                            openBeg, highBeg, lowBeg, closeBeg,
                                            volumeBeg, openInterestBeg );

               /* TA_HistoryAddData is ALWAYS the owner of these memory block
                * when called. So we set these to NULL to make sure there will
                * be no attempt to free these from this function.
                */
               openBeg = highBeg = lowBeg = closeBeg = NULL;
               timestampBeg = NULL;
               volumeBeg = openInterestBeg = NULL;
               nbTotalBarDone += nbBarAddedInTheBlock;
               nbBarAddedInTheBlock = 0;

               if( retCode != TA_SUCCESS )
                  goto exit_loops;

               retCode = TA_EstimateAllocNext( &estimationInfo, &nbElementToAllocate );
               if( retCode != TA_SUCCESS )
                  goto exit_loops;

               memoryNeeded = 1;
               SKIP_LINE;
            }
         }
         else
         {
            /* Make sure we did not hit an EOL or EOF prematurly, if yes,
             * this line will be silently ignored.
             */
            CHECK_EOL_EOF;
         }
      }

      goto op_loop;

exit_loops: /* Jump here when the end-of-file is hit (or an error occured) */

   /* On succesful exit, process possibly remaining data. */
   if( (retCode == TA_SUCCESS) && (nbBarAddedInTheBlock != 0) )
   {
      retCode = TA_HistoryAddData( paramForAddData, nbBarAddedInTheBlock,
                                   period, timestampBeg,
                                   openBeg, highBeg, lowBeg, closeBeg,
                                   volumeBeg, openInterestBeg );

      openBeg = highBeg = lowBeg = closeBeg = NULL;
      timestampBeg = NULL;
      volumeBeg = openInterestBeg = NULL;
      nbTotalBarDone += nbBarAddedInTheBlock;
   }
   
   /* ALWAYS verify if locally allocated memory needs to be freed. ALWAYS. */
   FREE_IF_NOT_NULL( openBeg );
   FREE_IF_NOT_NULL( highBeg );
   FREE_IF_NOT_NULL( lowBeg );
   FREE_IF_NOT_NULL( closeBeg );
   FREE_IF_NOT_NULL( volumeBeg );
   FREE_IF_NOT_NULL( openInterestBeg );
   FREE_IF_NOT_NULL( timestampBeg );

   /* An indication that no more data needs to be provided is not a failure. */
   if( retCode == TA_ENOUGH_DATA )
      retCode = TA_SUCCESS;

   /* Return the number of added price bar to the caller. */
   if( nbBarAdded )
      *nbBarAdded = nbTotalBarDone;

   TA_TRACE_RETURN( retCode );
}
コード例 #16
0
/**** Global functions definitions.   ****/
TA_RetCode TA_GetHistoryDataFromWeb( TA_Libc *libHandle,
                                     TA_DataSourceHandle *handle,
                                     TA_CategoryHandle   *categoryHandle,
                                     TA_SymbolHandle     *symbolHandle,
                                     TA_Period            period,
                                     const TA_Timestamp  *start,
                                     const TA_Timestamp  *end,
                                     TA_Field             fieldToAlloc,
                                     TA_ParamForAddData  *paramForAddData )
{
   TA_PROLOG;

   TA_RetCode retCode;
   TA_StringCache *stringCache;
   TA_String *yahooName;
   TA_WebPage *webPage;
   TA_PrivateYahooHandle *yahooHandle;
   TA_DecodingParam localDecodingParam;
   const TA_DecodingParam *decodingParam;
   TA_FileHandle *fileHandle;
   TA_ReadOpInfo *readOpInfo;
   UIRSuffixParsing suffixParsing;
   TA_Timestamp firstBarTimestamp, lastBarTimestamp, prevEndDate;
   TA_InfoFromAddedData infoFromAddedData;
   TA_DayOfWeek dayOfWeek;

   int nbEstimateBar;
   int nbField;
   unsigned int nbBarAdded, nbTotalBarAdded;
   int again, firstTime, nbBatch;
   int zeroBarAddedAttempt;

   TA_TRACE_BEGIN( libHandle, TA_GetHistoryDataFromWeb );

   /* Initialize some local variables. */
   stringCache   = TA_GetGlobalStringCache( libHandle );
   yahooHandle   = (TA_PrivateYahooHandle *)handle->opaqueData;
   readOpInfo    = NULL;
   nbEstimateBar = 0;

   TA_ASSERT( libHandle, categoryHandle != NULL );
   TA_ASSERT( libHandle, symbolHandle != NULL );
   TA_ASSERT( libHandle, categoryHandle->string != NULL );
   TA_ASSERT( libHandle, symbolHandle->string != NULL );

   /* Set the initial first/last timestamp */
   if( start )
      TA_TimestampCopy( &firstBarTimestamp, start );
   else
   {
      TA_SetDate( 1950, 1, 1, &firstBarTimestamp );
      TA_SetTime( 0, 0, 0, &firstBarTimestamp );
   }

   if( end )
      TA_TimestampCopy( &lastBarTimestamp, end );
   else
   {
      TA_SetDateNow( &lastBarTimestamp );
      TA_SetTime( 0, 0, 0, &lastBarTimestamp );
   }

   /* Make sure that lastBarTimestamp is a week-day. */
   dayOfWeek = TA_GetDayOfTheWeek( &lastBarTimestamp );
   if( (dayOfWeek == TA_SUNDAY) || (dayOfWeek == TA_SATURDAY) )
      TA_PrevWeekday( &lastBarTimestamp );

   /* Map the TA-Lib name into the Yahoo! name. */
   retCode = TA_AllocStringFromLibName( libHandle,
                                        categoryHandle->string,
                                        symbolHandle->string,
                                        &yahooName );  
   if( retCode != TA_SUCCESS )
   {
      TA_TRACE_RETURN( retCode );
   }

   TA_ASSERT( libHandle, yahooName != NULL );
   TA_ASSERT( libHandle, yahooHandle != NULL );

   /* Get the decoding parameter for the CSV web page. */
   decodingParam = TA_YahooIdxDecodingParam( yahooHandle->index, TA_YAHOOIDX_CVS_PAGE );
   if( !decodingParam )
   {
      TA_StringFree( stringCache, yahooName );
      TA_TRACE_RETURN( TA_INTERNAL_ERROR(103) );
   }

   /* Use a local copy of the decoding param. 
    * This is because the uirSuffix is replaced with
    * an allocated buffer (so the date field can be
    * manipulated).
    */
   localDecodingParam = *decodingParam;

   /* Parse the uirSuffix so the start/end date can be changed. */
   if( !setUIRSuffixParsing( decodingParam->uirSuffix, &suffixParsing ) )
   {
      /* This should never happen unless the
       * Yahoo! index protocol has been broken.
       */
      /* Clean-up and exit */
      TA_StringFree( stringCache, yahooName );
      TA_TRACE_RETURN( TA_INTERNAL_ERROR(104) );
   }

   /* Replace the uirSuffix with a large local buffer. */
   localDecodingParam.uirSuffix = TA_Malloc( libHandle, suffixParsing.maxTotalLength );
   if( !localDecodingParam.uirSuffix )
   {
      /* Clean-up and exit */
      TA_StringFree( stringCache, yahooName );
      TA_TRACE_RETURN( TA_ALLOC_ERR );
   }

   /* Change the dates in the uirSuffix. */
   buildUIRSuffix( &suffixParsing,
                   &firstBarTimestamp, &lastBarTimestamp,
                   (char *)localDecodingParam.uirSuffix );

   /* nbBatch is a safety net to make sure that
    * TA-Lib won't stay forever in the while loop
    * in case Yahoo! changes their protocol.
    */
   nbBatch = 0; 

   /* Sometime Yahoo! return an empty csv file. Make
    * multiple attempts in that case.
    */
   zeroBarAddedAttempt = 0;

   again = 1;
   firstTime = 1;
   nbTotalBarAdded = 0;
   while( again && (++nbBatch < 100) && (zeroBarAddedAttempt < 10) )
   {  
    
      if( TA_TimestampLess(&lastBarTimestamp,&firstBarTimestamp) )
      {
          /* Get out of this loop if all the requested data
           * has been retreived already.
           */
         again = 0;
         break;
      }   

      retCode = TA_WebPageAllocFromYahooName( libHandle,
                                              &localDecodingParam,
                                              TA_StringToChar(yahooName),
                                              &webPage );
           
      if( retCode != TA_SUCCESS )
      {
         TA_StringFree( stringCache, yahooName );
         TA_Free( libHandle, (char *)localDecodingParam.uirSuffix );
         TA_TRACE_RETURN( retCode );
      }

      /* Disguise the webPage stream into a "file". That way the speed
       * optimized ASCII decoder can be re-used (TA_ReadOp stuff).
       */
      retCode = TA_FileSeqOpenFromStream( libHandle, webPage->content, &fileHandle );
      if( retCode != TA_SUCCESS )
      {
         /* Clean-up and exit */
         TA_StringFree( stringCache, yahooName );
         TA_WebPageFree( webPage );
         TA_Free( libHandle, (char *)localDecodingParam.uirSuffix );
         TA_TRACE_RETURN( retCode );
      }

      if( firstTime )
      {
         /* Make assumption of the data provided
          * base on the number of fields in the CSV file.
          */
         nbField = nbCommaField( webPage->content );
         switch( nbField )
         {
         case 2:
            readOpInfo = yahooHandle->readOp2Fields;
            break;
         case 5:
            readOpInfo = yahooHandle->readOp5Fields;
            break;
         default:
            readOpInfo = yahooHandle->readOp6Fields;
         }

         /* User asking for all the fields? */
         if( fieldToAlloc == TA_ALL )
         {
            switch( nbField )
            {
            case 2:
               fieldToAlloc = TA_CLOSE|TA_TIMESTAMP;
               break;
            case 5:
               fieldToAlloc = TA_OPEN|TA_HIGH|TA_LOW|TA_CLOSE|TA_TIMESTAMP;
               break;
            default:
               fieldToAlloc = TA_OPEN|TA_HIGH|TA_LOW|TA_CLOSE|TA_VOLUME|TA_TIMESTAMP;
            }
         }

         /* Optimize the read op for the requested data. */
         retCode = TA_ReadOp_Optimize( libHandle,
                                       readOpInfo,
                                       period,
                                       fieldToAlloc );
         if( retCode != TA_SUCCESS )
         {
            /* Clean-up and exit */
            TA_StringFree( stringCache, yahooName );
            TA_WebPageFree( webPage );
            TA_Free( libHandle, (char *)localDecodingParam.uirSuffix );
            TA_TRACE_RETURN( retCode );
         }

         /* Make an estimation of the number of price bar. */
         nbEstimateBar  = TA_StreamCountChar( webPage->content, '\n' ) + 1;
         if( nbEstimateBar < 100 )
            nbEstimateBar = 100;
      }

      /* Interpret the CSV data. */
      retCode = TA_ReadOp_Do( libHandle, fileHandle,                           
                              readOpInfo,
                              period, &firstBarTimestamp, &lastBarTimestamp,
                              nbEstimateBar, fieldToAlloc,
                              paramForAddData,
                              &nbBarAdded );

      TA_FileSeqClose( libHandle, fileHandle );
      TA_WebPageFree( webPage );

      nbTotalBarAdded += nbBarAdded;

      if( retCode != TA_SUCCESS )
      {
         /* Clean-up and exit */
         TA_StringFree( stringCache, yahooName );
         TA_Free( libHandle, (char *)localDecodingParam.uirSuffix );
         TA_TRACE_RETURN( retCode );
      }

      /* Yahoo! does not always return all the data it could, up to
       * the requested end date. It is important to detect these occurence
       * and cancel the usage of all data accumulated up to now. 
       */      
      TA_GetInfoFromAddedData( paramForAddData, &infoFromAddedData );
      if( infoFromAddedData.barAddedSinceLastCall )
      {
         /* Do some more checking by considering holidays, week-end etc... */
         if( !isGapAcceptable(&infoFromAddedData.highestTimestampAddedSinceLastCall, &lastBarTimestamp) )
         {
            /* Clean-up and exit */
            TA_StringFree( stringCache, yahooName );
            TA_Free( libHandle, (char *)localDecodingParam.uirSuffix );
            TA_TRACE_RETURN( TA_DATA_GAP );
         }
         
         TA_TimestampCopy( &lastBarTimestamp, &infoFromAddedData.lowestTimestamp );
      }

      #if DEBUG_PRINTF
      printf( "NB BAR ADDED=%d, TOTAL=%d\n", nbBarAdded, nbTotalBarAdded );
      #endif

      /* Verify if more data should be processed. 
       * Yahoo! sometimes slice their data, in 
       * batch of 200 price bars. 
       */
      if( firstTime && (nbBarAdded > 200) )
      {
         again = 0; /* Assume all the data extracted... exit the loop. */
      }
      else if( nbBarAdded == 0 )
      {
         /* Make multiple attempts when retreiving data succeed,
          * but somehow there is zero bar returned. 
          *
          * Sometimes this might be correct when there is truly no
          * more data available, so choosing an algorithm before
          * giving up is a comprimise between reliability and
          * usability. The data source is free... and you get
          * what you pay for after all ;)
          */
         if( (nbTotalBarAdded < 1000) && (zeroBarAddedAttempt >= 1) && (zeroBarAddedAttempt < 7) )
         {
            /* I did choose to add a delay when insufficient total data is returned. When
             * there is already ~5 years of data, most likely there is "Zero" returned
             * because there is NO more data available, so just do the retry without delay.
             */
            TA_Sleep(zeroBarAddedAttempt*2);
         }

         #if DEBUG_PRINTF
         printf( "Retry %d", zeroBarAddedAttempt );
         #endif

         zeroBarAddedAttempt++;
      }
      else
      {
         zeroBarAddedAttempt = 0;

         if( TA_TimestampEqual( &lastBarTimestamp, &prevEndDate ) )
         {
            /* prevEndDate is a "safety net" to
             * exit the loop early in case Yahoo! starts
             * to return always the same batch of data.
             * Just ignore the repetitive data and exit.
             */
            TA_Free( libHandle, (char *)localDecodingParam.uirSuffix );
            TA_StringFree( stringCache, yahooName );
            TA_TRACE_RETURN( TA_SUCCESS );
         }
         TA_TimestampCopy( &prevEndDate, &lastBarTimestamp );

         /* Request the data up to the day BEFORE
          * the last batch of data received.
          */
         TA_PrevDay( &lastBarTimestamp );

         /* Make sure that lastBarTimestamp is a week-day. */
         dayOfWeek = TA_GetDayOfTheWeek( &lastBarTimestamp );
         if( (dayOfWeek == TA_SUNDAY) || (dayOfWeek == TA_SATURDAY) )
            TA_PrevWeekday( &lastBarTimestamp );

         /* Change the dates in the uirSuffix. */
         buildUIRSuffix( &suffixParsing,
                         &firstBarTimestamp, &lastBarTimestamp,
                         (char *)localDecodingParam.uirSuffix );

         /* From that point, data is expected to be most likely
          * sent in batch of 200.
          */
         nbEstimateBar = 200;
      }

      firstTime = 0;
   }

   /* Clean-up and exit */
   TA_Free( libHandle, (char *)localDecodingParam.uirSuffix );
   TA_StringFree( stringCache, yahooName );
   TA_TRACE_RETURN( retCode );
}
コード例 #17
0
static TA_RetCode equityPeriodTransform( TA_PMPriv     *pmPriv,
                                         TA_Period      newPeriod, /* The new desired period. */
                                         unsigned int  *nbBars,    /* Return the number of price bar */
                                         TA_Timestamp **timestamp, /* Allocate new timestamp. */
                                         TA_Real      **equity )   /* Allocate new equity. */
{
   TA_PROLOG

   /* Notice that this function is very similar to the
    * TA_PeriodTransform function in ta_period.c
    *
    * If you find a bug here, may be worth double
    * checking TA_PeriodTransform as well...
    */
   TA_RetCode retCode;

   /* Temporaries. */
   const TA_Timestamp *tempTimestamp;
   unsigned int tempInt, tempInt2;

   /* Variable used to identify period crossing. */
   unsigned int currentWeek, currentMonth, currentYear, currentQuarter;

   /* Pointer on the history being transformed. */
   const TA_Timestamp *old_timestamp;
   const TA_Real      *old_equity;
   TA_Integer          old_nbBars;

   /* Pointer on the transformed data. */
   TA_Timestamp *new_timestamp;    /* New allocated timestamp. */
   TA_Real      *new_equity;       /* New allocated open. */
   TA_Integer    new_nbBars;

   TA_Timestamp  cur_timestamp;    /* Current new timestamp of new period. */
   TA_Real       cur_equity;       /* Current new equity of new period. */

   int oldPriceBar, newPriceBar; /* Array iterators. */
   unsigned int again, periodCompleted; /* Boolean */
   int firstIteration;

   TA_TRACE_BEGIN(  TA_PeriodTransform );

   /* Validate some mandatory parameter. */
   TA_ASSERT( newPeriod != 0 );
   TA_ASSERT( nbBars  != NULL );

   /* It is assume that the caller call this function
    * when there is really a transform to do.
    */
   TA_ASSERT( newPeriod != TA_DAILY );

   /* Of course, timestamps from the source are needed. */
   TA_ASSERT( pmPriv->arrayTimestamp != NULL );

   /* Initialize all callers pointers to NULL.
    * These will be initialize only on success.
    * In the meantime, new_XXXX pointers are
    * going to be used on the new allocated data.
    */
   if( !timestamp || !equity ) 
      return TA_BAD_PARAM;

   *timestamp = NULL;
   *equity    = NULL;
   *nbBars    = 0;

   /* Validate the supported transformation. */

   /* Eliminate all the transform that
    * are currently not supported. 
    * Identify also the major steps
    * needed to perform the transformation.
    */
   switch( newPeriod )
   {
   case TA_WEEKLY:
   case TA_MONTHLY:
   case TA_QUARTERLY:
   case TA_YEARLY:
      /* These are supported. */
      break; 
   default:
      TA_TRACE_RETURN( TA_PERIOD_NOT_AVAILABLE );
   }

   /* OK.. now proceed with the transformations. 
    * The strategy is simple:
    *   The equity for the whole period will be the 
    *   equity at the last daily price bar of 
    *   that period.
    */
   old_timestamp    = &pmPriv->arrayTimestamp[0];
   old_equity       = &pmPriv->equity[0];
   old_nbBars       = pmPriv->nbDailyBars;

   new_timestamp    = NULL;
   newPriceBar      = 0;

   cur_timestamp.date = 0;    /* Current new timestamp of new period. */
   cur_timestamp.time = 0;    /* Current new timestamp of new period. */
   

   /* Overestimate the number of required new price bar. */
   switch( newPeriod )
   {
   case TA_WEEKLY:
      retCode = TA_TimestampDeltaWeek( &old_timestamp[0], &old_timestamp[old_nbBars-1], (unsigned int *)&new_nbBars );
         break;
   case TA_MONTHLY:
      retCode = TA_TimestampDeltaMonth( &old_timestamp[0], &old_timestamp[old_nbBars-1], (unsigned int *)&new_nbBars );
      break;
   case TA_QUARTERLY:
      retCode = TA_TimestampDeltaQuarter( &old_timestamp[0], &old_timestamp[old_nbBars-1], (unsigned int *)&new_nbBars );
      break;
   case TA_YEARLY:
      retCode = TA_TimestampDeltaYear( &old_timestamp[0], &old_timestamp[old_nbBars-1], (unsigned int *)&new_nbBars );
      break;
   default:
      TA_TRACE_RETURN( TA_INTERNAL_ERROR(126) );
   }

   if( retCode != TA_SUCCESS )
   {
      TA_TRACE_RETURN( retCode );
   }

   new_nbBars += 2; /* To be on the safe side */

   /* Allocate the new data. */      
   new_timestamp = TA_Malloc( new_nbBars * sizeof( TA_Timestamp ) );
   if( !new_timestamp )
   {
      TA_TRACE_RETURN( TA_ALLOC_ERR );
   }
   new_equity = TA_Malloc( new_nbBars * sizeof( TA_Real ) );
   if( !new_equity )
   {
      TA_Free(  new_timestamp );
      TA_TRACE_RETURN( TA_ALLOC_ERR );
   }
      
   /* Allows to detect crossing of the new period. */
   currentYear    = TA_GetYear ( &old_timestamp[0] );
   currentMonth   = TA_GetMonth( &old_timestamp[0] );
   currentWeek    = TA_GetWeekOfTheYear( &old_timestamp[0] );
   currentQuarter = TA_GetQuarterOfTheYear( &old_timestamp[0] );

   /* Iterate through the old price bar. */
   oldPriceBar = 0;

   /* Iterate through the new price bar. */
   newPriceBar = 0;

   again = 1; /* Becomes false when all bars are processed. */
   while( again )
   {
      /* Initialize cur_XXXXXX variables with the first bar in old timeframe. */
      cur_timestamp = old_timestamp[oldPriceBar];
      cur_equity    = old_equity   [oldPriceBar];

      /* Go through the bars and accumulate the info
       * until the end of the requested period is reach.
       */
      periodCompleted = 0;
      firstIteration = 1;
      while( (oldPriceBar < old_nbBars) && !periodCompleted )
      {
         tempTimestamp = &old_timestamp[oldPriceBar];

         /* Check if we reached an end of period. */
         switch( newPeriod )
         {
         case TA_WEEKLY:
            tempInt  = TA_GetWeekOfTheYear( tempTimestamp );

            /* Trap weeks on years boundary. */
            if( (currentWeek == 52) && (tempInt == 0) )
               currentWeek = 0;
            else if( currentWeek != tempInt )
            {
               periodCompleted = 1;
               currentWeek = tempInt;
            }
            break;
         case TA_MONTHLY:
            tempInt  = TA_GetMonth( tempTimestamp );
            tempInt2 = TA_GetYear(tempTimestamp);
            if( (currentMonth != tempInt) ||
                (currentYear  != tempInt2) )
            {
               periodCompleted = 1;
               currentMonth    = tempInt;
               currentYear     = tempInt2;
            }
            break;
         case TA_QUARTERLY:
            tempInt = TA_GetQuarterOfTheYear( tempTimestamp );
            tempInt2 = TA_GetYear(tempTimestamp);

            if( (currentQuarter != tempInt) ||
                (currentYear    != tempInt2) )
            {
                  periodCompleted = 1;
                  currentQuarter  = tempInt;
                  currentYear     = tempInt2;
            }
            break;
         case TA_YEARLY:
            tempInt = TA_GetYear( tempTimestamp );
            if( currentYear != tempInt )
            {
               periodCompleted = 1;
               currentYear = tempInt;
            }
            break;
         default:
            /* Do nothing */
            break;
         }

         /* If this is not the end of a period (in the new timeframe)
          * just accumulate the data. If this is the end of the period
          * that while loop will be exited.
          * Nothing is done on the first iteration because all the 
          * cur_XXXX variables have been already initialized.
          */
         if( !periodCompleted )
         {
            if( !firstIteration )
            {
               /* Adjust the new price bar. */
               cur_timestamp = old_timestamp[oldPriceBar];
               cur_equity    = old_equity   [oldPriceBar];
            }
            else
               firstIteration = 0;

            /* Move to next bar. */
            oldPriceBar++;
         }
      }
      /* We got all the info needed in the cur_XXXXX variables for
       * proceeding with the initialization of the new period price bar.
       */
      TA_DEBUG_ASSERT( newPriceBar < new_nbBars );

      /* If the timestamp is requested, some adjustment could be
       * needed to cur_timestamp.
       */
      switch( newPeriod )
      {
      case TA_WEEKLY:
            /* Now something a little bit tricky, we must
             * make sure that this new price bar is reported
             * as being the Friday of that week (even if there 
             * is no price bar for that Friday).
             */
            TA_JumpToDayOfWeek( &cur_timestamp, TA_FRIDAY );
            break;
      case TA_MONTHLY:
            /* Monthly timestamp always end with the last day of
             * the month. Even if there was no actual transaction
             * the last day.
             */
            TA_JumpToEndOfMonth( &cur_timestamp );
            break;
      case TA_QUARTERLY:
            /* Quarterly timestamp always end with the last day of
             * the quarter. Even if there was no actual transaction
             * the last day.
             * Quarter 1 =  3/31
             * Quarter 2 =  6/30
             * Quarter 3 =  9/30
             * Quarter 4 = 12/31
             */
            TA_JumpToEndOfQuarter( &cur_timestamp );
            break;
      case TA_YEARLY:
            /* Yearly data always end on 12/31. */
            TA_JumpToEndOfYear( &cur_timestamp );
            break;
      default:
            /* Do nothing. */
            break;
      }

      /* The new price bar is initialized here. */
      new_timestamp[newPriceBar] = cur_timestamp;
      new_equity   [newPriceBar] = cur_equity;
                     
      /* This new period bar is completed, move to the next one. */
      newPriceBar++;

      /* Any more data to process? */
      if( oldPriceBar >= old_nbBars)
         again = 0; /* All bars have been processsed. */
   }

   /* All done! Return the final result to the caller. */
   *equity    = new_equity;
   *timestamp = new_timestamp;
   *nbBars    = newPriceBar;

   TA_TRACE_RETURN( TA_SUCCESS );
}
コード例 #18
0
TA_RetCode TA_FileSeqOpen( const char *path, TA_FileHandle **handle )
{
   TA_PROLOG
   TA_FileHandlePriv *fileHandlePriv;

   TA_TRACE_BEGIN(  TA_FileSeqOpen );

   TA_ASSERT( path != NULL );
   TA_ASSERT( handle != NULL );

   fileHandlePriv = (TA_FileHandlePriv *)TA_Malloc( sizeof( TA_FileHandlePriv ) );
   if( !fileHandlePriv )
   {
      TA_TRACE_RETURN( TA_ALLOC_ERR );
   }
   memset( fileHandlePriv, 0, sizeof( TA_FileHandlePriv ) );

   #if defined( USE_WIN32_API )
   fileHandlePriv->handle = CreateFile( path, GENERIC_READ, FILE_SHARE_READ,
                                        NULL, OPEN_EXISTING,
                                        FILE_FLAG_NO_BUFFERING|FILE_FLAG_SEQUENTIAL_SCAN,
                                        NULL );

   if( fileHandlePriv->handle == INVALID_HANDLE_VALUE )
   {
      TA_FileSeqClose( (TA_FileHandle *)fileHandlePriv );
      TA_TRACE_RETURN( TA_ACCESS_FAILED );
   }
   #else
   /* For all non-win32 platform, use standard ANSI C I/O */
   fileHandlePriv->handle = fopen( path, "rb" );

   if( fileHandlePriv->handle == 0 )
   {
      TA_FileSeqClose( (TA_FileHandle *)fileHandlePriv );
      TA_TRACE_RETURN( TA_ACCESS_FAILED );
   }
   #endif

   /* Allocate buffer memory. */
   #if defined( USE_WIN32_API )
      fileHandlePriv->allocBuffer = allocDiskBuffer( path, &fileHandlePriv->allocBufferSize );
      if( !fileHandlePriv->allocBuffer || (fileHandlePriv->allocBufferSize == 0) )
      {
         TA_FileSeqClose( (TA_FileHandle *)fileHandlePriv );
         TA_TRACE_RETURN( TA_ACCESS_FAILED );
      }
   #else
      fileHandlePriv->allocBuffer = TA_Malloc( FILE_BUFFER_SIZE );
      fileHandlePriv->allocBufferSize = FILE_BUFFER_SIZE;
      if( !fileHandlePriv->allocBuffer )
      {
         TA_FileSeqClose( (TA_FileHandle *)fileHandlePriv );
         TA_TRACE_RETURN( TA_ACCESS_FAILED );
      }
   #endif

   /* Keep a ptr on the path. */
   fileHandlePriv->path = path;

   /* Success! Return the info to the caller. */
   *handle = (TA_FileHandle *)fileHandlePriv;
   TA_TRACE_RETURN( TA_SUCCESS );
}
コード例 #19
0
/**** Global functions definitions.   ****/
TA_RetCode TA_ReadOp_Optimize( TA_ReadOpInfo *readOpInfo,
                               TA_Period      period,
                               TA_Field       fieldToAlloc )
{
   TA_PROLOG
   TA_ReadOp *lastOp;
   unsigned int tmpIdx;
   unsigned int i, nbReadOp;
   unsigned int flagSet;
   TA_Field field;
   TA_ReadOp *readOp;
    
   TA_TRACE_BEGIN(  TA_OptimizeReadOp );

   TA_ASSERT( fieldToAlloc != 0 );

   nbReadOp = readOpInfo->nbReadOp;
   readOp = readOpInfo->arrayReadOp;

   /* Skip all fields not requested. */
   for( i=0; i < nbReadOp; i++ )
   {
      if( TA_IS_PERMANENT_SKIP_SET(readOp[i]) )
      {
         TA_SET_SKIP_FLAG(readOp[i]);
      }
      else
      {
         TA_CLR_SKIP_FLAG(readOp[i]);
         field = TA_ReadOpToField( readOp[i] );

         if( field == TA_TIMESTAMP )
         {
            tmpIdx = TA_GET_IDX(readOp[i]);
            switch( period )
            {
            case TA_YEARLY:
               /* No need for anything shorter than year in the timestamp. */
               if( tmpIdx <= TA_MONTH_IDX )
               {
                  TA_SET_SKIP_FLAG(readOp[i]);
                  TA_SET_NB_NUMERIC(readOp[i],1);
               }
               break;

            case TA_MONTHLY:
               /* No need for anything shorter than days in the timestamp. */
               if( tmpIdx <= TA_DAY_IDX )
               {
                  TA_SET_SKIP_FLAG(readOp[i]);
                  TA_SET_NB_NUMERIC(readOp[i],1);
               }
               break;

            case TA_DAILY:
               /* No need for hour,min,sec in the timestamp. */
               if( tmpIdx <= TA_HOUR_IDX )
               {
                  TA_SET_SKIP_FLAG(readOp[i]);
                  TA_SET_NB_NUMERIC(readOp[i],1);
               }
               break;
            default:
               /* Do nothing. */
               break;
            }
         }
         else if( !(field&fieldToAlloc) )
         {
            /* This field is not requested for being allocated. */
            TA_SET_SKIP_FLAG(readOp[i]);
            TA_SET_NB_NUMERIC(readOp[i],1);
         }
      }
   }

   TA_ASSERT( TA_IS_LAST_SET(readOp[nbReadOp-1]) );

   /* Determine the last needed field. Mark it with the STOP flag.
    * Make sure all previous get their STOP flag clear.
    */
   flagSet = 0;
   for( i=nbReadOp; i > 0; i-- )
   {
      lastOp = &readOp[i-1];
      if( flagSet )
      {
         TA_CLR_READ_STOP_FLAG(*lastOp);
      }
      else
      {
         TA_SET_READ_STOP_FLAG(*lastOp);

         if( !TA_IS_SKIP_SET(*lastOp) )
           flagSet = 1;
      }
   }

   TA_TRACE_RETURN( TA_SUCCESS );
}
コード例 #20
0
TA_RetCode TA_ReadOpInfoAlloc( const char *sourceInfo,
                               TA_ReadOpInfo **allocatedInfo,
                               unsigned int readOpFlags )
{
   TA_PROLOG
   TA_RetCode retCode;

   TA_ReadOp readOp;
   TA_ReadOp *arrayReadOp;
   TA_ReadOpInfo *newReadOpInfo;
   TA_Field fieldMask, fieldProvided;
   unsigned int timeframeIdx;
   unsigned int intraDayIncPeriod;
   TA_TokenId   intraDayIncToken;
   TA_TokenId   tempToken;
   unsigned int tempInt;
   unsigned int period;
   unsigned int errorOccurred;

   const char *pos;
   unsigned int inField;
   unsigned int nbField;
   unsigned int nbCharInField;
   unsigned int skipNonDigitLine;
   const char *ptrFirstCarInField;

   unsigned char localBuf[10];
   unsigned int bufIdx, opIdx, i;

   register unsigned int flagSet;
   register TA_ReadOp *ptrReadOp;
   
   TA_TRACE_BEGIN(  TA_BuildArrayReadOp );

   newReadOpInfo = (TA_ReadOpInfo *)TA_Malloc( sizeof( TA_ReadOpInfo ) );

   /* These variables are resolved within this function. */
   memset( newReadOpInfo, 0, sizeof( TA_ReadOpInfo ) );

   /* At this point, TA_ReadOpInfoFree can be safely called. */

   /* Keep track of some user provided parameter. */
   newReadOpInfo->sourceInfo = sourceInfo;
   newReadOpInfo->readOpFlags = readOpFlags;

   /* Initialize some defaults. */
   newReadOpInfo->openInterestMult = 100;
   newReadOpInfo->volumeMult       = 100;

   nbField = 0;
   intraDayIncPeriod = 0;
   intraDayIncToken = TA_TOK_END;

   pos = newReadOpInfo->sourceInfo;
   if( !pos || (*pos == '\0') )
   {
      TA_ReadOpInfoFree( newReadOpInfo );
      TA_TRACE_RETURN( TA_MISSING_FIELD );
   }

   /* Find how many fields are defined and check some syntax
    * at the same time.
    */
   if( *pos != '[' )
   {
      TA_ReadOpInfoFree( newReadOpInfo );
      TA_TRACE_RETURN( TA_INVALID_FIELD );
   }

   inField = 0;
   nbCharInField = 0;
   skipNonDigitLine = 0;
   ptrFirstCarInField = NULL;
   while( *pos != '\0' )
   {
      switch( *pos )
      {
      case '[':
         if( inField )
         {
            TA_ReadOpInfoFree( newReadOpInfo );
            TA_TRACE_RETURN( TA_INVALID_FIELD );
         }
         inField = 1;
         break;
      case ']':
         if( (!inField) || (nbCharInField == 0) )
         {
            TA_ReadOpInfoFree( newReadOpInfo );
            TA_TRACE_RETURN( TA_INVALID_FIELD );
         }

         nbField++;

         /* Exclude fields not generating a TA_ReadOp.
          * For the time being that means only the -H and -NDL field.
          */
         if( nbCharInField >= 2 )
         {
            TA_ASSERT( ptrFirstCarInField != NULL );
            if( ptrFirstCarInField[0] == '-' ) 
            {
               if( toupper(ptrFirstCarInField[1]) == 'H' )
                  nbField--;
               else if( (toupper(ptrFirstCarInField[1]) == 'N') &&
                        (toupper(ptrFirstCarInField[2]) == 'D') &&
                        (toupper(ptrFirstCarInField[3]) == 'L') )
               {
                  skipNonDigitLine = 1;
                  nbField--;
               }               
             }
         }

         inField = 0;
         nbCharInField = 0;
         ptrFirstCarInField = NULL;
         break;
      default:
         if( !inField )
         {
            TA_ReadOpInfoFree( newReadOpInfo );
            TA_TRACE_RETURN( TA_INVALID_FIELD );
         }

         if( nbCharInField == 0 )
            ptrFirstCarInField = pos;
         nbCharInField++;
         break;
      }

      pos++;
   }

   if( inField || *(pos-1) != ']' )
   {
      TA_ReadOpInfoFree( newReadOpInfo );
      TA_TRACE_RETURN( TA_INVALID_FIELD );
   }

   /* Build the TA_ReadOp array */
   arrayReadOp = (TA_ReadOp *)TA_Malloc( sizeof( TA_ReadOp ) * nbField );

   if( !arrayReadOp )
   {
      TA_ReadOpInfoFree( newReadOpInfo );
      TA_TRACE_RETURN( TA_ALLOC_ERR );
   }

   newReadOpInfo->arrayReadOp = arrayReadOp;

   pos = TA_StringToChar(newReadOpInfo->sourceInfo);

   bufIdx = 0;
   opIdx = 0;
   while( *pos != '\0' && (opIdx < nbField) )
   {
      switch( *pos )
      {
      case '[':
        break;

      case ']':
        localBuf[bufIdx] ='\0';
        bufIdx = 0;

        /* Identify the field and build the TA_ReadOp. */
        tempInt = 0;
        retCode = buildReadOp( newReadOpInfo,
                               (const char *)&localBuf[0],
                               &arrayReadOp[opIdx],
                               &tempToken, &tempInt );
        if( retCode != TA_SUCCESS )
        {
           TA_ReadOpInfoFree( newReadOpInfo );
           TA_TRACE_RETURN( retCode );
        }

        if( arrayReadOp[opIdx] != 0 )
        {
           /* Set the replace zero flag as needed */
           if( TA_IS_REPLACE_ZERO(readOpFlags) && TA_IS_REAL_CMD(arrayReadOp[opIdx]) )
           {
              TA_SET_REPLACE_ZERO(arrayReadOp[opIdx]);
           }

           /* Set the skipNonDigitLine flag as needed. */
           if( skipNonDigitLine == 1 )
           {
              TA_SET_SKIP_NDL_FLAG(arrayReadOp[opIdx]);
           }

           /* Ooof... this readOp is now all build! */
           opIdx++;
        }

        /* If this is a time token, make sure this
         * is not in contradiction with an already
         * specified increment.
         */
        if( intraDayIncPeriod )
        {
           errorOccurred = 0;
           switch( tempToken )
           {
           case TA_TOK_SEC:
           case TA_TOK_SS:
              if( (intraDayIncToken == TA_TOK_MIN) ||
                  (intraDayIncToken == TA_TOK_MN) )
                 errorOccurred = 1;
              /* no break */
           case TA_TOK_MIN:
           case TA_TOK_MN:
              if( (intraDayIncToken == TA_TOK_HOUR) ||
                  (intraDayIncToken == TA_TOK_HH) )
                 errorOccurred = 1;
              break;
           case TA_TOK_HOUR:
           case TA_TOK_HH:
              errorOccurred = 1;
              break;
           default:
              /* Do nothing */
              break;
           }

           if( errorOccurred )
           {
              TA_ReadOpInfoFree( newReadOpInfo );
              TA_TRACE_RETURN( TA_INVALID_FIELD );
           }
        }

        /* Check if a period increment is specified. */
        if( (tempInt != 0) && (tempInt != 1) )
        {
           if( intraDayIncPeriod != 0 )
           {
              TA_ReadOpInfoFree( newReadOpInfo );
              TA_TRACE_RETURN( TA_INVALID_FIELD );
           }

           intraDayIncPeriod = tempInt;
           intraDayIncToken  = tempToken;
        }
        break;

      default:
        if( bufIdx >= sizeof(localBuf)-1 )
        {
           TA_ReadOpInfoFree( newReadOpInfo );
           TA_TRACE_RETURN( TA_INVALID_FIELD );
        }

        localBuf[bufIdx++] = *pos;
        break;
      }

      pos++;
   }

   if( opIdx != nbField )
   {
      TA_ReadOpInfoFree( newReadOpInfo );
      TA_TRACE_RETURN( TA_INTERNAL_ERROR(89) );
   }

   arrayReadOp[opIdx-1] |= TA_CMD_LAST_FLAG;

   /* Build the mask representing the fields provided. */
   fieldProvided = 0;
   timeframeIdx = TA_INTEGER_ARRAY_SIZE;

   for( opIdx=0; opIdx < nbField; opIdx++ )
   {
      readOp = arrayReadOp[opIdx];

      TA_ASSERT( readOp != 0 ); /* Parano test */

      if( !TA_IS_PERMANENT_SKIP_SET(readOp) )
      {
         /* Make sure this field was not specified twice. */
         for( i=opIdx+1; i < nbField; i++ )
         {
            if( (TA_IS_REAL_CMD(readOp) && TA_IS_REAL_CMD(arrayReadOp[i])) ||
                (TA_IS_INTEGER_CMD(readOp) && TA_IS_INTEGER_CMD(arrayReadOp[i])) )
            {
               if( (TA_GET_IDX(readOp) == TA_GET_IDX(arrayReadOp[i])) &&
                   !TA_IS_PERMANENT_SKIP_SET(arrayReadOp[i]) )
               {
                  TA_ReadOpInfoFree( newReadOpInfo );
                  TA_TRACE_RETURN( TA_REDUNDANT_FIELD );
               }
            }
         }

         /* Parano test: Double-check redundant field in a different way. */
         fieldMask = TA_ReadOpToField( readOp );
         TA_ASSERT( fieldMask != 0 );
         if( !(fieldMask & TA_TIMESTAMP) && (fieldProvided & fieldMask) )
         {
            TA_ReadOpInfoFree( newReadOpInfo );
            TA_TRACE_RETURN( TA_REDUNDANT_FIELD );
         }

         /* Set the field. */
         fieldProvided |= fieldMask;

         /* Keep track of the smallest granularity of the timestamp. */
         if( fieldMask & TA_TIMESTAMP )
         {
            if( (timeframeIdx == TA_INTEGER_ARRAY_SIZE) ||
                (TA_GET_IDX(readOp) < timeframeIdx) )
               timeframeIdx = TA_GET_IDX(readOp);
         }
      }
   }


   /* No date/time reference provided!? This is considered an error
    * in the current implementation.
    */
   if( timeframeIdx == TA_INTEGER_ARRAY_SIZE )
   {
      TA_ReadOpInfoFree( newReadOpInfo );
      TA_TRACE_RETURN( TA_MISSING_DATE_OR_TIME_FIELD );
   }

   /* Determine at which point the timestamp is completed. */
   flagSet = 0;
   for( opIdx=nbField; opIdx > 0; opIdx-- )
   {
      ptrReadOp = &arrayReadOp[opIdx-1];
      readOp = *ptrReadOp;

      if( !flagSet                          && 
          TA_IS_INTEGER_CMD(readOp)         && 
          (TA_GET_IDX(readOp)<=TA_YEAR_IDX) && 
          !TA_IS_PERMANENT_SKIP_SET(readOp) )
      {
         TA_SET_TIMESTAMP_COMPLETE(*ptrReadOp);
         flagSet = 1;
      }
      else
      {
         TA_CLR_TIMESTAMP_COMPLETE(*ptrReadOp);
      }
   }

   /* Validate and identify the period. */
   period = 0;
   if( intraDayIncPeriod )
   {
      errorOccurred = 0;
      switch( timeframeIdx )
      {
      case TA_YEAR_IDX:
      case TA_MONTH_IDX:
      case TA_DAY_IDX:
         errorOccurred = 1;
         break;
      case TA_HOUR_IDX:
         if( (intraDayIncPeriod < TA_1HOUR) || (intraDayIncPeriod >= TA_DAILY) )
            errorOccurred = 1;
         break;
      case TA_MIN_IDX:
         if( (intraDayIncPeriod < TA_1MIN) || (intraDayIncPeriod >= TA_1HOUR) )
            errorOccurred = 1;
         break;
      case TA_SEC_IDX:
         if( (intraDayIncPeriod < TA_1SEC) || (intraDayIncPeriod >= TA_1MIN) )
            errorOccurred = 1;
         break;
      default:
         TA_ReadOpInfoFree( newReadOpInfo );
         TA_FATAL(  NULL, timeframeIdx, fieldProvided );
      }

      if( errorOccurred )
      {
         TA_ReadOpInfoFree( newReadOpInfo );
         TA_TRACE_RETURN( TA_INVALID_FIELD );
      }
            
      period = intraDayIncPeriod;
   }
   else
   {
      switch( timeframeIdx )
      {
      case TA_YEAR_IDX:
         period = TA_YEARLY;
         break;
      case TA_MONTH_IDX:
         period = TA_MONTHLY;
         break;
      case TA_DAY_IDX:
         period = TA_DAILY;
         break;
      case TA_HOUR_IDX:
         period = TA_1HOUR;
         break;
      case TA_MIN_IDX:
         period = TA_1MIN;
         break;
      case TA_SEC_IDX:
         period = TA_1SEC;
         break;
      default:
         TA_FATAL(  NULL, timeframeIdx, fieldProvided );
      }
   }

   /* A last check... */
   if( period == 0 )
   {
      TA_ReadOpInfoFree( newReadOpInfo );
      TA_TRACE_RETURN( TA_INVALID_FIELD );
   }
         
   /* Everything is fine, let's return the information. */
   newReadOpInfo->arrayReadOp = arrayReadOp;
   newReadOpInfo->fieldProvided = fieldProvided;
   newReadOpInfo->nbReadOp = nbField;
   newReadOpInfo->period = period;

   *allocatedInfo = newReadOpInfo;

   TA_TRACE_RETURN( TA_SUCCESS );
}
コード例 #21
0
TA_RetCode TA_FileIndexAddSymbolData( TA_Libc *libHandle,
                                      TA_FileIndexCategoryData *categoryData,
                                      TA_String *stringSymbol,
                                      TA_ValueTreeNode *treeNodeValue,
                                      TA_FileIndexSymbolData **added )
{
   TA_PROLOG;
   TA_RetCode retCode;
   TA_FileIndexSymbolData *symbolData;
   unsigned int tmpInt;
   unsigned int symbolFound; /* Boolean */
   TA_StringCache *stringCache;

   TA_TRACE_BEGIN( libHandle, TA_FileIndexAddSymbolData );

   stringCache = TA_GetGlobalStringCache( libHandle );

   TA_ASSERT( libHandle, categoryData != NULL );
   TA_ASSERT( libHandle, categoryData->listSymbol != NULL );
   TA_ASSERT( libHandle, stringSymbol != NULL );
   TA_ASSERT( libHandle, treeNodeValue != NULL );

   if( added )
      *added = NULL;

   /* Trap the case where this symbol is already there for that
    * category. In that case, the information is ignored.
    * Under the same category, for the same datasource, only one file
    * is supported for a category-symbol pair.
    */
   symbolData = (TA_FileIndexSymbolData *)TA_ListAccessTail( categoryData->listSymbol );

   symbolFound = 0;
   while( symbolData && !symbolFound )
   {
      TA_ASSERT( libHandle, symbolData->string != NULL );

      tmpInt = strcmp( TA_StringToChar( stringSymbol ),
                       TA_StringToChar( symbolData->string ) );
      if( tmpInt == 0 )
         symbolFound = 1;
      else
         symbolData = (TA_FileIndexSymbolData *)TA_ListAccessPrev( categoryData->listSymbol );
   }

   if( !symbolFound )
   {
      /* This is a new symbol, so allocate the TA_FileIndexSymbolData */
      symbolData = (TA_FileIndexSymbolData *)TA_Malloc( libHandle, sizeof(TA_FileIndexSymbolData) );

      if( !symbolData )
      {
         TA_TRACE_RETURN( TA_ALLOC_ERR );
      }

      /* Initialize the TA_FileIndexSymbolData */
      symbolData->parent = categoryData;
      symbolData->node   = treeNodeValue;
      symbolData->string = TA_StringDup( stringCache, stringSymbol );
      if( !symbolData->string )
      {
         TA_Free( libHandle, symbolData );
         TA_TRACE_RETURN( TA_ALLOC_ERR );
      }

      /* Add it to the category list. */
      retCode = TA_ListAddTail( categoryData->listSymbol, symbolData );
      if( retCode != TA_SUCCESS )
      {
         TA_StringFree( stringCache, symbolData->string );
         TA_Free( libHandle, symbolData );
         TA_TRACE_RETURN( TA_ALLOC_ERR );
      }
   }

   /* Return the address of the object representing that symbol. */
   if( added )
      *added = symbolData;


   TA_TRACE_RETURN( TA_SUCCESS );
}
コード例 #22
0
/**** Global functions definitions.   ****/
TA_RetCode TA_FileIndexParsePath( TA_FileIndexPriv *fileIndexPriv, TA_String *path )
{
   typedef enum { INIT_PROCESSING,
                  FIX_PROCESSING,
                  FIELD_PROCESSING,
                  WILD_PROCESSING,
                  SEP_PROCESSING } State;

   TA_PROLOG
   State currentState;
   const char *currentTokenStart;
   unsigned int length;
   char *str;
   char *pos;
   char sepTmp[2];
   TA_RetCode retCode;
   unsigned int tokenSize;
   TA_TokenId tokenId;
   const char *sourcePattern;

   TA_TRACE_BEGIN(  TA_FileIndexParsePath );

   TA_ASSERT( path != NULL );

   sepTmp[1] = '\0';
   sourcePattern = TA_StringToChar( path );

   /* The following macro should help for the readability of the parsing logic.
    * These macro are used only inside this function.
    */
   #define RETURN(y) {TA_Free(str); TA_TRACE_RETURN( y );}
   #define REJECT_STATE(x,y) { if(currentState==x)RETURN(y);  }
   #define CHANGE_STATE(x) {currentState=x; currentTokenStart=pos+1;}

   #define ADD_TOKEN(id,value) \
   { \
      retCode = addToken(fileIndexPriv,id,value); \
      if( retCode != TA_SUCCESS) RETURN(retCode); \
   }

   #define FLUSH_FIX() \
   { \
      retCode = flushFixPart(fileIndexPriv,currentTokenStart,pos); \
      if( retCode != TA_SUCCESS ) RETURN(retCode); \
   }

   /* This function build a list representing the tokens
    * of the sourcePattern.
    *
    * Example:  "C:\a\*AZD?\[S]\data.txt" becomes
    *
    *            TokenId      Value
    *            TA_TOK_FIX       "C:"
    *            TA_TOK_SEP       "\"
    *            TA_TOK_FIX       "a"
    *            TA_TOK_SEP       "\"
    *            TA_TOK_WILD      "*"
    *            TA_TOK_FIX       "AZD"
    *            TA_TOK_WILD_CHAR "?"
    *            TA_TOK_SEP       "\"
    *            TA_TOK_S         "?*"
    *            TA_TOK_SEP       "\"
    *            TA_TOK_FIX       "data.txt"
    *            TA_TOK_END       (null)
    *
    *        In the values, the '?' and '*' character represent MS-DOS kind
    *        of wildcards:
    *             '?' is any character (but only one).
    *             '*' zero or more of any character
    */
   if( sourcePattern == NULL )
      return TA_INVALID_PATH;

   length = strlen( sourcePattern ) + 1;

   if( (length <= 1) || (length > 2048) )
      return TA_INVALID_PATH;

   str = (char *)TA_Malloc( length );
   strcpy( str, sourcePattern );

   pos = str;
   currentState = INIT_PROCESSING;
   currentTokenStart = pos;

   while( *pos != '\0' )
   {

      if( (*pos == '\\') || (*pos == '/') )
      {
         /* Handle directories separator character. */
         REJECT_STATE( FIELD_PROCESSING, TA_INVALID_FIELD );
         REJECT_STATE( SEP_PROCESSING, TA_INVALID_PATH );

         FLUSH_FIX();

#if 0
!!! Needed?
         /* Check that the string prior to the separator
          * does not terminate with a dot '.'
          */
         if( currentState != INIT_PROCESSING )
         {
            if( *(pos-1) == '.' )
               RETURN( TA_INVALID_PATH );
         }
#endif
         /* Transform into the directory delimiter
          * used on the host file system.
          */
         sepTmp[0] = (char)TA_SeparatorASCII();
         ADD_TOKEN( TA_TOK_SEP, sepTmp );

         CHANGE_STATE( SEP_PROCESSING );
      }
      else switch( *pos )
コード例 #23
0
static TA_RetCode buildReadOp( TA_ReadOpInfo *readOpInfo,
                               const char *localBuf,
                               TA_ReadOp *readOp,
                               TA_TokenId *tokenId,
                               unsigned int *intraDayIncrementInSeconds )
{
   TA_PROLOG
   TA_TokenId id;
   TA_ReadOp tmpReadOp;
   TA_RetCode retCode;
   TA_Integer optionalParam;
   unsigned int mult, intraDayIncrement;

   TA_TRACE_BEGIN(  buildReadOp );

   if( !readOp || !intraDayIncrementInSeconds || !tokenId )
   {
      TA_TRACE_RETURN( TA_INTERNAL_ERROR(9) );
   }

   *intraDayIncrementInSeconds = 0;
   *readOp = 0;
   *tokenId = 0;

   retCode = findTokenId( localBuf, &id, &optionalParam );

   if( retCode != TA_SUCCESS )
   {
      TA_TRACE_RETURN( retCode );
   }

   TA_ASSERT( id != TA_TOK_END );

   /* Trap special token not generating a TA_ReadOp. */
   if( id == TA_TOK_SKIP_N_HEADER_LINE )
   {
      if( optionalParam == 0 )
      {
         TA_TRACE_RETURN( TA_INVALID_FIELD );
      }
      readOpInfo->nbHeaderLineToSkip = optionalParam;
      TA_TRACE_RETURN( TA_SUCCESS );
   }

   if( id == TA_TOK_SKIP_NON_DIGIT_LINE )
   {
      if( optionalParam != 1 )
      {
         TA_TRACE_RETURN( TA_INVALID_FIELD );
      }
      TA_TRACE_RETURN( TA_SUCCESS );
   }

   /* Integer or Real operation? */
   switch( id )
   {
   case TA_TOK_OPEN:
   case TA_TOK_HIGH:
   case TA_TOK_LOW:
   case TA_TOK_CLOSE:
   case TA_TOK_SKIP_N_REAL:
      tmpReadOp = TA_CMD_READ_REAL;
      break;
   case TA_TOK_YYYY:
   case TA_TOK_YY:
   case TA_TOK_Y:
   case TA_TOK_M:
   case TA_TOK_MM:
   case TA_TOK_MMM:
   case TA_TOK_D:
   case TA_TOK_DD:
   case TA_TOK_VOLUME:
   case TA_TOK_OPENINTEREST:
   case TA_TOK_HOUR:
   case TA_TOK_MIN:
   case TA_TOK_SEC:
   case TA_TOK_HH:
   case TA_TOK_MN:
   case TA_TOK_SS:
   case TA_TOK_SKIP_N_INTEGER:
      tmpReadOp = TA_CMD_READ_INTEGER;
      break;
   case TA_TOK_SKIP_N_CHAR:
   case TA_TOK_SKIP_NON_DIGIT_LINE:
      tmpReadOp = 0;
      break;
   default:
      TA_TRACE_RETURN( TA_INVALID_FIELD );
   }

   /* Is this a permanent skip operation? */
   switch( id )
   {
   case TA_TOK_SKIP_N_CHAR:
   case TA_TOK_SKIP_N_INTEGER:
   case TA_TOK_SKIP_N_REAL:
      TA_SET_PERMANENT_SKIP_FLAG( tmpReadOp );
      TA_SET_SKIP_FLAG( tmpReadOp );
      break;
   default:
      TA_CLR_PERMANENT_SKIP_FLAG( tmpReadOp );
      TA_CLR_SKIP_FLAG( tmpReadOp );
   }

   /* Set the "numeric" parameter */
   switch( id )
   {
   case TA_TOK_SKIP_N_INTEGER:
   case TA_TOK_SKIP_N_REAL:
   case TA_TOK_SKIP_N_CHAR:
      TA_SET_NB_NUMERIC( tmpReadOp, optionalParam );
      break;
   case TA_TOK_OPENINTEREST:
      readOpInfo->openInterestMult = optionalParam;
      TA_SET_NB_NUMERIC( tmpReadOp, 0 );
      break;
   case TA_TOK_VOLUME:
      readOpInfo->volumeMult = optionalParam;
      TA_SET_NB_NUMERIC( tmpReadOp, 0 );
      break;
   default:
      TA_SET_NB_NUMERIC( tmpReadOp, TA_TokenMaxSize(id) );
      break;
   }

   /* Set the index information. */
   switch( id )
   {
   case TA_TOK_YYYY:
   case TA_TOK_YY:
   case TA_TOK_Y:
      TA_SET_IDX( tmpReadOp, TA_YEAR_IDX );
      break;
   case TA_TOK_M:
   case TA_TOK_MM:
   case TA_TOK_MMM:
      TA_SET_IDX( tmpReadOp, TA_MONTH_IDX );
      break;
   case TA_TOK_D:
   case TA_TOK_DD:
      TA_SET_IDX( tmpReadOp, TA_DAY_IDX );
      break;
   case TA_TOK_OPEN:
      TA_SET_IDX( tmpReadOp, TA_OPEN_IDX );
      break;
   case TA_TOK_HIGH:
      TA_SET_IDX( tmpReadOp, TA_HIGH_IDX );
      break;
   case TA_TOK_LOW:
      TA_SET_IDX( tmpReadOp, TA_LOW_IDX );
      break;
   case TA_TOK_CLOSE:
      TA_SET_IDX( tmpReadOp, TA_CLOSE_IDX );
      break;
   case TA_TOK_VOLUME:
      TA_SET_IDX( tmpReadOp, TA_VOLUME_IDX );
      break;
   case TA_TOK_OPENINTEREST:
      TA_SET_IDX( tmpReadOp, TA_OPENINTEREST_IDX );
      break;
   case TA_TOK_HOUR:
   case TA_TOK_HH:
      TA_SET_IDX( tmpReadOp, TA_HOUR_IDX );
      break;
   case TA_TOK_MIN:
   case TA_TOK_MN:
      TA_SET_IDX( tmpReadOp, TA_MIN_IDX );
      break;
   case TA_TOK_SEC:
   case TA_TOK_SS:
      TA_SET_IDX( tmpReadOp, TA_SEC_IDX );
      break;
   default:
      /* Do nothing. */
      break;
   }

   /* Set a special flag for the TA_TOK_MMM because
    * it must do chat to integer processing.
    */
   if( id == TA_TOK_MMM )
      tmpReadOp |= TA_CMD_READ_MONTH_CHAR;

   /* Identify the time increments. */
   mult = 1;
   intraDayIncrement = 0;

   switch( id )
   {
   case TA_TOK_HOUR:
   case TA_TOK_HH:
      mult *= 60;
   case TA_TOK_MIN:
   case TA_TOK_MN:
      mult *= 60;
   case TA_TOK_SEC:
   case TA_TOK_SS:
      if( optionalParam < 1 )
      {
         /* Shall be at least '1'... */
         TA_TRACE_RETURN( TA_INVALID_FIELD );
      }
      else if( optionalParam > 1 )
      {
         /* When the default '1' is specified, do
          * not return the increment to the caller.
          */
         intraDayIncrement = optionalParam * mult;
      }
      break;
   default:
      /* Do nothing */
      break;
   }

   /* Everything is fine, return the info to the caller. */
   *readOp = tmpReadOp;
   *intraDayIncrementInSeconds = intraDayIncrement;
   *tokenId = id;

   TA_TRACE_RETURN( TA_SUCCESS );
}
コード例 #24
0
ファイル: ta_abstract.c プロジェクト: royratcliffe/ta-lib
TA_RetCode TA_ForEachFunc( TA_Libc *libHandle, TA_CallForEachFunc functionToCall, void *opaqueData )
{
   TA_PROLOG;
   TA_StringTable   *tableGroup;
   TA_StringTable   *tableFunc;
   const TA_FuncDef *funcDef;
   const TA_FuncHandle *funcHandle;
   TA_RetCode retCode;
   unsigned int i, j;

   const TA_FuncInfo *funcInfo;

   TA_TRACE_BEGIN( libHandle, TA_ForEachFunc );

   if( functionToCall == NULL )
   {
      TA_TRACE_RETURN( TA_BAD_PARAM );
   }
   
   /* Get all the group to iterate. */
   retCode = TA_GroupTableAlloc( libHandle, &tableGroup );

   if( retCode == TA_SUCCESS )
   {
      TA_ASSERT( libHandle, tableGroup != NULL );

      for( i=0; i < tableGroup->size; i++ )
      {
         TA_DEBUG_ASSERT( libHandle, tableGroup->string[i] != NULL );

         /* Get all the symbols to iterate for this category. */
         retCode = TA_FuncTableAlloc( libHandle, tableGroup->string[i], &tableFunc );


         if( retCode == TA_SUCCESS )
         {
            TA_DEBUG_ASSERT( libHandle, tableFunc != NULL );

            for( j=0; j < tableFunc->size; j++ )
            {
               TA_DEBUG_ASSERT( libHandle, tableFunc->string[j] != NULL );

               /* Get the function handle, and then the TA_FuncDef,
                * and then the TA_FuncInfo...
                */
               retCode = TA_GetFuncHandle( libHandle, tableFunc->string[j], &funcHandle );

               if( retCode != TA_SUCCESS )
                  continue;

               TA_DEBUG_ASSERT( libHandle, funcHandle != NULL );

               funcDef  = (const TA_FuncDef *)funcHandle;

               TA_DEBUG_ASSERT( libHandle, funcDef != NULL );

               funcInfo = funcDef->funcInfo;

               TA_DEBUG_ASSERT( libHandle, funcInfo != NULL );

               /* Call user provided function. */
               (*functionToCall)( libHandle, funcInfo, opaqueData );
            }
         }

         TA_FuncTableFree( tableFunc );
      }

      TA_GroupTableFree( tableGroup );
   }
   else
   {
      TA_TRACE_RETURN( TA_INTERNAL_ERROR(2) );
   }

   TA_TRACE_RETURN( TA_SUCCESS );
}
コード例 #25
0
static TA_RetCode fetchUsingLibCurl( TA_NetworkGlobal *global,
                                     TA_WebPage       *webPage )
{
   TA_PROLOG

   TA_RetCode retCode;
   TA_WebPageHiddenData *webPageHidden;
   const char *string1, *string2, *string3;
   unsigned int urlLength;
   char *urlString;
   CURLcode retValue;
   long curlInfo;

   TA_TRACE_BEGIN( fetchUsingLibCurl );

   TA_ASSERT( webPage != NULL );

   webPageHidden = (TA_WebPageHiddenData *)webPage->hiddenData;   
  
   /* Open an internet session. */

   /* Create the URL. */
   string1 = "http://";
   urlLength = strlen( string1 ) + 1;
   if( webPageHidden->webSiteAddr )
   {
      string2 = webPageHidden->webSiteAddr;
      urlLength += strlen( string2 );
   }
   else
      string2 = NULL;

   if( webPageHidden->webSitePage )
   {
      string3 = webPageHidden->webSitePage;
      urlLength += strlen( string3 ) + 1;
   }
   else
      string3 = NULL;

   urlString = TA_Malloc( urlLength );
   if( !urlString )
   {
      TA_TRACE_RETURN( TA_ALLOC_ERR );
   }
   sprintf( urlString, "%s%s%s%s", string1? string1:"",
                             string2? string2:"", 
                             string3 && string3[0] != '/'? "/":"", 
                             string3? string3:"" );
   
   /* Serialize the request until a stress testing 
    * application proove that libcurl is multi-thread safe.
    */
   #if !defined( TA_SINGLE_THREAD )
      retCode = TA_SemaWait( &global->mutexSema );
      if( retCode != TA_SUCCESS )
      {
         TA_Free(  urlString );
         TA_TRACE_RETURN( retCode );
      }
   #endif

   /* Specify URL to get */
   curl_easy_setopt(global->curlHandle, CURLOPT_URL, urlString );
 
   /* Send all data to the callback function  */
   curl_easy_setopt(global->curlHandle, CURLOPT_WRITEFUNCTION,
                    libcurlWriteMemoryCallback);
 
   /* Specify the opaque data ptr for the callback function */
   curl_easy_setopt(global->curlHandle, CURLOPT_FILE, (void *)webPage);

   /* Fetch it. */
   retValue = curl_easy_perform(global->curlHandle);

   if( retValue == CURLE_OK )
      retCode = TA_SUCCESS;
   else
   {
      retValue = curl_easy_getinfo( global->curlHandle, CURLINFO_HTTP_CODE, &curlInfo );
      if( retValue == CURLE_OK )
         retCode = rfc1945StatusToRetCode( curlInfo );
      else
         retCode = TA_HTTP_SC_UNKNOWN;
   }

   #if !defined( TA_SINGLE_THREAD )
      TA_SemaPost( &global->mutexSema  );
   #endif

   /* Free the url. */
   TA_Free(  urlString );

   TA_TRACE_RETURN( retCode );
}
コード例 #26
0
TA_RetCode TA_SIMULATOR_GetHistoryData( TA_DataSourceHandle *handle,
                                        TA_CategoryHandle   *categoryHandle,
                                        TA_SymbolHandle     *symbolHandle,
                                        TA_Period            period,
                                        const TA_Timestamp  *start,
                                        const TA_Timestamp  *end,
                                        TA_Field             fieldToAlloc,
                                        TA_ParamForAddData  *paramForAddData )
{
   TA_PROLOG
   TA_PrivateHandle *privateHandle;
   TA_RetCode retCode;
   TA_Timestamp *timestamp;
   TA_Real *open, *high, *low, *close;
   TA_Integer *volume;
   unsigned int i;

   (void)fieldToAlloc;
   (void)end;
   (void)start;
   (void)period;

   TA_TRACE_BEGIN(  TA_SIMULATOR_GetHistoryData );

   TA_ASSERT( handle != NULL );

   privateHandle = (TA_PrivateHandle *)handle->opaqueData;
   TA_ASSERT( privateHandle != NULL );
   TA_ASSERT( paramForAddData != NULL );
   TA_ASSERT( categoryHandle != NULL );
   TA_ASSERT( symbolHandle != NULL );

   retCode = TA_INTERNAL_ERROR(98);

   /* Note: start/end index are currently ignored
    *       in this data source.
    */

   /* Identify the category. */
   switch( (unsigned int)categoryHandle->opaqueData )
   {
   case 0: /* This is TA_SIM_REF */
      switch( (unsigned int)symbolHandle->opaqueData )
      {
      case 0:
          timestamp = (TA_Timestamp *)NULL;
          open = high = low = close = (TA_Real *)NULL;
          volume = (TA_Integer *)NULL;

          #define TA_ALLOC_COPY( varName, varType, varSize) { \
             varName = TA_Malloc( sizeof( varType ) * varSize ); \
             if( !varName ) \
             { \
                FREE_IF_NOT_NULL( open         ); \
                FREE_IF_NOT_NULL( high         ); \
                FREE_IF_NOT_NULL( low          ); \
                FREE_IF_NOT_NULL( close        ); \
                FREE_IF_NOT_NULL( volume       ); \
                TA_TRACE_RETURN( TA_ALLOC_ERR ); \
             } \
             memcpy( varName, TA_SREF_##varName##_daily_ref_0_PRIV, sizeof( varType )*varSize ); }

             TA_ALLOC_COPY( open,      TA_Real,      TA_REF_DAILY_NB_BARS );
             TA_ALLOC_COPY( high,      TA_Real,      TA_REF_DAILY_NB_BARS );
             TA_ALLOC_COPY( low,       TA_Real,      TA_REF_DAILY_NB_BARS );
             TA_ALLOC_COPY( close,     TA_Real,      TA_REF_DAILY_NB_BARS );
             TA_ALLOC_COPY( volume,    TA_Integer,   TA_REF_DAILY_NB_BARS );         
         #undef TA_ALLOC_COPY

         /* Set the timestamp. */
         timestamp = TA_Malloc( sizeof( TA_Timestamp ) * TA_REF_DAILY_NB_BARS );
         if( !timestamp )
         {
            TA_Free(  open   );
            TA_Free(  high   );
            TA_Free(  low    );
            TA_Free(  close  );
            TA_Free(  volume );
            TA_TRACE_RETURN( TA_ALLOC_ERR );
         }

         for( i=0; i < TA_REF_DAILY_NB_BARS; i++ )
            TA_TimestampCopy( &timestamp[i], &TA_SREF_timestamp_daily_ref_0_PRIV[i] );

          retCode = TA_HistoryAddData( paramForAddData,
                                       TA_REF_DAILY_NB_BARS, TA_DAILY,                                      
                                       timestamp,
                                       open, high,                                      
                                       low, close,
                                       volume, NULL );                                      
          break;

      case 1:
          /* Allocate the rest. */
          timestamp = (TA_Timestamp *)NULL;
          open = high = low = close = (TA_Real *)NULL;

          #define TA_ALLOC_COPY( varName, varType, varSize) { \
                  varName = TA_Malloc( sizeof( varType ) * varSize ); \
                  if( !varName ) \
                  { \
                     TA_Free(  timestamp ); \
                     FREE_IF_NOT_NULL( open      ); \
                     FREE_IF_NOT_NULL( high      ); \
                     FREE_IF_NOT_NULL( low       ); \
                     FREE_IF_NOT_NULL( close     ); \
                     TA_TRACE_RETURN( TA_ALLOC_ERR ); \
                  } \
                  memcpy( varName, TA_SREF_##varName##_daily_ref_0_PRIV, sizeof( varType )*varSize ); }

         TA_ALLOC_COPY( open,      TA_Real,      33 );
         TA_ALLOC_COPY( high,      TA_Real,      33 );
         TA_ALLOC_COPY( low,       TA_Real,      33 );
         TA_ALLOC_COPY( close,     TA_Real,      33 );
         #undef TA_ALLOC_COPY

         /* Set the timestamp. */
         timestamp = (TA_Timestamp *)TA_Malloc( sizeof( TA_Timestamp ) * 33 );
         if( !timestamp )
         {
            FREE_IF_NOT_NULL( open  );
            FREE_IF_NOT_NULL( high  );
            FREE_IF_NOT_NULL( low   );
            FREE_IF_NOT_NULL( close );
            TA_TRACE_RETURN( TA_ALLOC_ERR );
         }

         for( i=0; i < TA_REF_INTRA_NB_BARS; i++ )
            TA_TimestampCopy( &timestamp[i], &TA_SREF_timestamp_intra_ref_0_PRIV[i] );

         retCode = TA_HistoryAddData( paramForAddData,
                                      TA_REF_INTRA_NB_BARS, TA_1MIN*10,
                                      timestamp,
                                      open, high,                                      
                                      low, close,                                      
                                      NULL, NULL );
                                      
         break;
      }
      break;

   case 1: /* This is TA_SIM_MRG */
      retCode = addSimMrgData( privateHandle, 
                               paramForAddData );
      break;
   }

   TA_TRACE_RETURN( retCode );
}
コード例 #27
0
TA_RetCode TA_WebPageAllocFromYahooName( TA_Libc *libHandle,
                                         const TA_DecodingParam *decodingParam,
                                         const char *yahooName,
                                         TA_WebPage **allocatedWebPage )
{
   TA_PROLOG;
   TA_RetCode retCode;
   char webSitePage[300];
   unsigned int prefixLength, suffixLength, symbolLength, i;
   const char *webSiteAddr;
   const char *uirPrefix, *uirSuffix;
   TA_WebPage *webPage;

   TA_TRACE_BEGIN( libHandle, TA_WebPageAllocFromYahooName );

   retCode = TA_INTERNAL_ERROR(117);

   if( !decodingParam || !yahooName || !allocatedWebPage )
   {
      TA_TRACE_RETURN( TA_BAD_PARAM );
   }

   webSiteAddr  = decodingParam->webSiteServer;
   TA_ASSERT( libHandle, webSiteAddr != NULL );

   uirPrefix = decodingParam->uirPrefix;
   TA_ASSERT( libHandle, uirPrefix != NULL );
   prefixLength = strlen( uirPrefix );

   uirSuffix = decodingParam->uirSuffix;
   TA_ASSERT( libHandle, uirSuffix != NULL );
   suffixLength = strlen( uirSuffix );
   
   symbolLength = strlen( yahooName );
   if( (symbolLength + suffixLength + prefixLength) >= 299 )
   {
      TA_TRACE_RETURN( TA_INVALID_SECURITY_EXCHANGE );
   }

   sprintf( webSitePage, "%s%s%s", uirPrefix, yahooName, uirSuffix );

   /* Get the Web Page */   
   for( i=0; i < 10; i++ )
   {
      retCode = TA_WebPageAlloc( libHandle,
                                 webSiteAddr,
                                 webSitePage,
                                 NULL, NULL, &webPage, 10 );

      if( retCode == TA_SUCCESS )
         break;
      else
      {         
         /* Yahoo! is may be slow, let's sleep 1 minute */
         TA_Sleep( 60 ); 
      }
   }

   if( retCode != TA_SUCCESS )
   {
      TA_TRACE_RETURN( retCode );
   }

   *allocatedWebPage = webPage;
   TA_TRACE_RETURN( TA_SUCCESS );
}
コード例 #28
0
TA_RetCode TA_YAHOO_OpenSource( const TA_AddDataSourceParamPriv *param,
                                TA_DataSourceHandle **handle )
{
   TA_PROLOG
   TA_DataSourceHandle *tmpHandle;
   TA_PrivateYahooHandle *privData;
   TA_RetCode retCode;
   TA_StringCache *stringCache;
   TA_CountryId countryId;
   TA_CountryId countryIdTemp;
   TA_Timestamp now;
   const char *locationPtr;
   char locationBuffer[3];
   int timeout_set; /* boolean */
   int i, again;
   unsigned int strLength, strServerLength;
   const char *strTemp;

   *handle = NULL;

   TA_TRACE_BEGIN( TA_YAHOO_OpenSource );

   stringCache = TA_GetGlobalStringCache();

   /* Verify that the requested functionality is supported or not. */
   if( param->flags & TA_REPLACE_ZERO_PRICE_BAR )
   {
      TA_TRACE_RETURN( TA_NOT_SUPPORTED );
   }

   /* Allocate and initialize the handle. This function will also allocate the
    * private handle (opaque data).
    */
   tmpHandle = TA_YAHOO_DataSourceHandleAlloc();

   if( tmpHandle == NULL )
   {
      TA_TRACE_RETURN( TA_ALLOC_ERR );
   }

   privData = (TA_PrivateYahooHandle *)(tmpHandle->opaqueData);

   /* Copy some parameters in the private handle. */
   privData->param = param;
   
   /* Indentify the country and replace with the default as needed.
    * At the same time, identify optional "server=" modifier.
    */
   countryId = TA_Country_ID_INVALID;
   if( privData->param->location )
   {
      locationPtr = TA_StringToChar(privData->param->location);

      /* Split into token (seperator is ';'). Check for a 2 character country 
       * string and the optional "server=" modifier.
       */
      i = -1; 
      strTemp = &locationPtr[0];
      strLength = 0;
      strServerLength = strlen(TA_SERVER_STR);
      again = 1;
      while( (++i < 1024) && again )
      {
         if( strLength == 0 )
            strTemp = &locationPtr[i];

         if( locationPtr[i] == '\0' )
            again = 0;         

         if( locationPtr[i] == ';' || !again )
         {
            if( strLength == 2 )
            {
               locationBuffer[0] = locationPtr[i-2];
               locationBuffer[1] = locationPtr[i-1];
               locationBuffer[2] = '\0';
               countryIdTemp = TA_CountryAbbrevToId(locationBuffer);
               if( countryIdTemp == TA_Country_ID_INVALID )
                  TA_TRACE_RETURN( TA_UNSUPPORTED_COUNTRY );
               if( countryId != TA_Country_ID_INVALID )
                  TA_TRACE_RETURN( TA_LIMIT_OF_ONE_COUNTRY_ID_EXCEEDED );
               countryId = countryIdTemp;         
            }
            else if( strLength>strServerLength && (strncmp(strTemp,TA_SERVER_STR,strServerLength)==0) )
            {              
               if( privData->userSpecifiedServer )
                  TA_TRACE_RETURN( TA_LIMIT_OF_ONE_SERVER_EXCEEDED );
               privData->userSpecifiedServer = TA_StringAllocN( stringCache, 
                                                                &strTemp[strServerLength],
                                                                strLength-strServerLength );
               TA_ASSERT( privData->userSpecifiedServer != NULL );
            }
            else
               TA_TRACE_RETURN( TA_LOCATION_PARAM_INVALID );

            strLength = 0;           
         }
         else
            strLength++;
      }
   }

   if( countryId == TA_Country_ID_INVALID )
   {
      /* Default is United States. */
      countryId = TA_Country_ID_US;
   }

   if( privData->param->id == TA_YAHOO_ONE_SYMBOL )
   {
      privData->index = NULL;
      privData->webSiteCountry = countryId;
      privData->webSiteSymbol  = TA_StringDup(stringCache,privData->param->info);
      tmpHandle->nbCategory = 1;
   }
   else
   {
      /* Build the index using .dat files */
      switch( countryId )
      {
      case TA_Country_ID_US: /* United States */
      case TA_Country_ID_CA: /* Canada */
      case TA_Country_ID_UK: /* United Kingdom */
      case TA_Country_ID_DE: /* Germany */
      case TA_Country_ID_DK: /* Denmark */
      case TA_Country_ID_ES: /* Spain */
      case TA_Country_ID_FR: /* France */
      case TA_Country_ID_IT: /* Italy */
      case TA_Country_ID_SE: /* Sweden */
      case TA_Country_ID_NO: /* Norway */
         /* These country are currently supported. */
         break;
      default:
         TA_YAHOO_DataSourceHandleFree( tmpHandle );
         TA_TRACE_RETURN( TA_UNSUPPORTED_COUNTRY );
      }

      /* Establish the timeout for local cache of the index.
       * Let's make it 4 business days.
       */
      timeout_set = 0;
      TA_SetDefault( &now );
      retCode = TA_SetDateNow( &now );
      for( i=0; (i < 4) && (retCode == TA_SUCCESS); i++ )
         retCode = TA_PrevWeekday( &now );
      if( (i == 4) && (retCode == TA_SUCCESS) )
         timeout_set = 1;
      
      /* At this point, we got all the information we
       * need in the handle.
       * Now build the TA_YahooIdx.
       */
      retCode = TA_YahooIdxAlloc( countryId,
                                  &privData->index,
                                  TA_USE_LOCAL_CACHE|TA_USE_REMOTE_CACHE,
                                  NULL, timeout_set?&now:NULL, NULL );

      if( retCode != TA_SUCCESS )
      {
         TA_YAHOO_DataSourceHandleFree( tmpHandle );
         TA_TRACE_RETURN( retCode );
      }

      /* Set the total number of distinct category. */
      tmpHandle->nbCategory = privData->index->nbCategory;
   }

   *handle = tmpHandle;

   TA_TRACE_RETURN( TA_SUCCESS );
}
コード例 #29
0
TA_RetCode TA_YAHOO_GetHistoryData( TA_DataSourceHandle *handle,
                                    TA_CategoryHandle   *categoryHandle,
                                    TA_SymbolHandle     *symbolHandle,
                                    TA_Period            period,
                                    const TA_Timestamp  *start,
                                    const TA_Timestamp  *end,
                                    TA_Field             fieldToAlloc,
                                    TA_ParamForAddData  *paramForAddData )
{
   TA_PROLOG
   TA_RetCode tempRetCode, retCode;
   TA_PrivateYahooHandle *yahooHandle;
   int again, j;

   TA_TRACE_BEGIN( TA_YAHOO_GetHistoryData );

   TA_ASSERT( handle != NULL );
   TA_ASSERT( paramForAddData != NULL );
   TA_ASSERT( categoryHandle != NULL );
   TA_ASSERT( symbolHandle != NULL );

   yahooHandle = (TA_PrivateYahooHandle *)handle->opaqueData;
   TA_ASSERT( yahooHandle != NULL );

   /* If the requested period is too precise for the
    * period that can be provided by this data source,
    * simply return without error.
    * Since no data has been added, the TA-LIB will ignore
    * this data source.
    */
   if( period < TA_DAILY )
   {
      TA_TRACE_RETURN( TA_SUCCESS );
   }

   /* Get the data from the WEB.
    *
    * Yahoo! sometimes have "gaps" in its data (like one
    * week missing), when this is being detected, we throw
    * away all the data up to now and start over (up to
    * 5 times before giving up).
    */
   again = 5;
   do
   {
      retCode = TA_GetHistoryDataFromWeb( handle,                                       
                                          categoryHandle, symbolHandle,
                                          TA_DAILY, start, end,                                            
                                          fieldToAlloc, paramForAddData );
      if( retCode == TA_DATA_GAP )
      {
         retCode = TA_HistoryAddDataReset( paramForAddData );
         if( retCode != TA_SUCCESS )
            again = 0; /* Give up */
         else
         {
            --again; /* Try again */

            /* Sometimes giving Yahoo! a break helps. */
            tempRetCode = TA_DriverShouldContinue(paramForAddData);
            j = 0;
            while( (j++ < 5) && (tempRetCode != TA_DATA_RETREIVE_TIMEOUT) )
            {
               TA_Sleep(1);
               tempRetCode = TA_DriverShouldContinue(paramForAddData);
            }
            if( tempRetCode == TA_DATA_RETREIVE_TIMEOUT )
            {
               retCode = tempRetCode;
               again = 0;            
            }
         }
      }
      else
      {
         again = 0; /* Exit the loop */
      }
   } while( again > 0 );


   TA_TRACE_RETURN( retCode );   
}
コード例 #30
0
TA_RetCode TA_FileIndexAddCategoryData( TA_FileIndexPriv *data,
                                        TA_String *stringCategory,
                                        TA_FileIndexCategoryData **added )
{
   TA_PROLOG;
   TA_RetCode retCode;
   TA_FileIndexCategoryData *categoryData;
   unsigned int tmpInt;
   unsigned int categoryFound; /* Boolean */
   TA_Libc *libHandle;
   TA_StringCache *stringCache;

   libHandle   = data->libHandle;
   TA_TRACE_BEGIN( libHandle, TA_FileIndexAddCategoryData );

   stringCache = TA_GetGlobalStringCache( libHandle );

   TA_ASSERT( libHandle, data != NULL );
   TA_ASSERT( libHandle, stringCategory != NULL );

   /* Trap the case where the category is already added. */
   categoryData = (TA_FileIndexCategoryData *)TA_ListAccessTail( data->listCategory );

   categoryFound = 0;
   while( categoryData && !categoryFound )
   {
      TA_ASSERT( libHandle, categoryData->string != NULL );

      tmpInt = strcmp( TA_StringToChar( stringCategory ),
                       TA_StringToChar( categoryData->string ) );
      if( tmpInt == 0 )
         categoryFound = 1;
      else
         categoryData = (TA_FileIndexCategoryData *)TA_ListAccessPrev( data->listCategory );
   }

   if( !categoryFound )
   {
      /* This is a new category, so allocate the TA_FileIndexCategoryData */
      categoryData = (TA_FileIndexCategoryData *)TA_Malloc( libHandle, sizeof(TA_FileIndexCategoryData) );

      if( !categoryData )
         TA_TRACE_RETURN( TA_ALLOC_ERR );

      /* Initialize the TA_FileIndexCategoryData */
      categoryData->parent = data;
      if( stringCategory )
      {
         categoryData->string = TA_StringDup( stringCache, stringCategory);    /* String for this category. Can be NULL. */
         if( !categoryData->string )
         {
            TA_Free( libHandle, categoryData );
            TA_TRACE_RETURN( TA_ALLOC_ERR );
         }
      }
      else
         categoryData->string = NULL;

      categoryData->listSymbol = TA_ListAlloc( libHandle );

      if( !categoryData->listSymbol )
      {
         if( categoryData->string )
            TA_StringFree( stringCache, categoryData->string );
         TA_Free( libHandle, categoryData );
         TA_TRACE_RETURN( TA_ALLOC_ERR );
      }

      /* Add it to the TA_FileIndexPriv */
      retCode = TA_ListAddTail( data->listCategory, categoryData );
      if( retCode != TA_SUCCESS )
      {
         TA_ListFree( categoryData->listSymbol );
         if( categoryData->string )
            TA_StringFree( stringCache, categoryData->string );
         TA_Free( libHandle, categoryData );
         TA_TRACE_RETURN( TA_ALLOC_ERR );
      }

      #if 0
         printf( "**ADDING CATEGORY[%s]\n", TA_StringToChar( categoryData->string ) );
      #endif
   }

   /* Return the address of the object representing that category. */
   if( added )
      *added = categoryData;


   TA_TRACE_RETURN( TA_SUCCESS );
}