3 votes

L'insertion d'une table étalée conduit à une erreur : `cast'.

J'ai construit un prototype de chargeur de données qui enregistre les CSV dans des tableaux évasés. Le flux de travail est le suivant :

  1. Créez le schéma la première fois, par ex. volatilitysurface table :

    volatilitysurface::([date:`datetime$(); ccypair:`symbol$()] atm_convention:`symbol$(); premium_included:`boolean$(); smile_type:`symbol$(); vs_type:`symbol$(); delta_ratio:`float$(); delta_setting:`float$(); wing_extrapolation:`float$(); spread_type:`symbol$());
  2. Pour chaque fichier dans le dossier rawdata, importez-le :

    myfiles:@[system;"dir /b /o:gn ",string `$getenv[`KDBRAWDATA],"*.volatilitysurface.csv 2> nul";()];
    if[myfiles~();.lg.o[`load;"no volatilitysurface files found!"];:0N];
    .lg.o[`load;"loading data files ..."];
    / load each file
    {
      mypath:"" sv (string `$getenv[`KDBRAWDATA];x);
      .lg.o[`load;"loading file name '",mypath,"' ..."];
      myfile:hsym`$mypath;
      tmp1:select date,ccypair,atm_convention,premium_included,smile_type,vs_type,delta_ratio,delta_setting,wing_extrapolation,spread_type from update date:x, premium_included:?[premium_included = `$"true";1b;0b] from ("ZSSSSSFFFS";enlist ",")0:myfile;
      `volatilitysurface upsert tmp1;
    } @/: myfiles;
    delete tmp1 from `.;
    .Q.gc[];
    .lg.o[`done;"loading volatilitysurface data done"];
    
    .lg.o[`save;"saving volatilitysurface schema to ",string afolder];
    volatilitysurface::0!volatilitysurface;
    .Q.dpft[afolder;`;`ccypair;`volatilitysurface];
    .lg.o[`cleanup;"removing volatilitysurface from memory"];
    delete volatilitysurface from `.;
    .Q.gc[];
    .lg.o[`done;"saving volatilitysurface schema done"];

Cela fonctionne parfaitement. J'utilise .Q.gc[]; fréquemment pour éviter de heurter la wsfull . Lorsque de nouveaux fichiers CSV sont disponibles, j'ouvre le schéma existant, je l'insère et le sauvegarde à nouveau, écrasant ainsi le système de fichiers HDB existant.

  1. Schéma ouvert :

    .lg.o[`open;"tables already exists, opening the schema ..."];
    @[system;"l ",(string afolder) _ 0;{.lg.e[`open;"failed to load hdb directory: ", x]; 'x}];
    / Re-create table index
    volatilitysurface::`date`ccypair xkey select from volatilitysurface;
  2. Exécutez à nouveau l'étape 2 pour ajouter les nouveaux fichiers CSV aux fichiers existants. volatilitysurface le premier CSV est parfaitement inséré mais le deuxième CSV échoue avec :

    error: `cast

J'ai débogué jusqu'au point d'erreur et, pour vérifier, j'ai vu que les métadonnées de l'application tmp1 y volatilitysurface sont parfaitement identiques. Avez-vous une idée de la raison pour laquelle cela se produit ? J'ai le même problème avec n'importe quelle autre table. J'ai essayé de nettoyer les clés de la table après chaque upsert, mais cela n'a pas aidé.

volatilitysurface::0!volatilitysurface;
volatilitysurface::`date`ccypair xkey volatilitysurface;

Et la comparaison des métadonnées au moment de l'erreur de distribution :

meta tmp1
c                 | t f a
------------------| -----
date              | z    
ccypair           | s    
atm_convention    | s    
premium_included  | b    
smile_type        | s    
vs_type           | s    
delta_ratio       | f    
delta_setting     | f    
wing_extrapolation| f    
spread_type       | s

meta volatilitysurface
c                 | t f a
------------------| -----
date              | z    
ccypair           | s   p
atm_convention    | s    
premium_included  | b    
smile_type        | s    
vs_type           | s    
delta_ratio       | f    
delta_setting     | f    
wing_extrapolation| f    
spread_type       | s   

UPDATE En m'inspirant de la réponse ci-dessous, j'ai essayé d'utiliser le système Torq. .loader.loadallfiles comme ceci (elle n'échoue pas mais rien ne se passe non plus, la table n'est pas créée en mémoire et les données ne sont pas écrites dans la base de données) :

.loader.loadallfiles[`headers`types`separator`tablename`dbdir`dataprocessfunc!(`x`ccypair`atm_convention`premium_included`smile_type`vs_type`delta_ratio`delta_setting`wing_extrapolation`spread_type;"ZSSSSSFFFS";enlist ",";`volatilitysurface;`:hdb; {[p;t] select date,ccypair,atm_convention,premium_included,smile_type,vs_type,delta_ratio,delta_setting,wing_extrapolation,spread_type from update date:x, premium_included:?[premium_included = `$"true";1b;0b] from t}); `:rawdata]

UDPATE2 C'est la sortie que j'obtiens de TorQ :

2017.11.20D08:46:12.550618000|wsp18497wn|dataloader|dataloader1|INF|dataloader|**** LOADING :rawdata/20171102_113420.disccurve.csv ****
2017.11.20D08:46:12.550618000|wsp18497wn|dataloader|dataloader1|INF|dataloader|reading in data chunk
2017.11.20D08:46:12.566218000|wsp18497wn|dataloader|dataloader1|INF|dataloader|Read 10000 rows
2017.11.20D08:46:12.566218000|wsp18497wn|dataloader|dataloader1|INF|dataloader|processing data
2017.11.20D08:46:12.566218000|wsp18497wn|dataloader|dataloader1|INF|dataloader|Enumerating
2017.11.20D08:46:12.566218000|wsp18497wn|dataloader|dataloader1|INF|dataloader|writing 4525 rows to :hdb/2017.09.12/volatilitysurface/
2017.11.20D08:46:12.581819000|wsp18497wn|dataloader|dataloader1|INF|dataloader|writing 4744 rows to :hdb/2017.09.13/volatilitysurface/
2017.11.20D08:46:12.659823000|wsp18497wn|dataloader|dataloader1|INF|dataloader|writing 731 rows to :hdb/2017.09.14/volatilitysurface/
2017.11.20D08:46:12.737827000|wsp18497wn|dataloader|dataloader1|INF|init|retrieving sort settings from :C:/Dev/torq//config/sort.csv
2017.11.20D08:46:12.737827000|wsp18497wn|dataloader|dataloader1|INF|sort|sorting the volatilitysurface table
2017.11.20D08:46:12.737827000|wsp18497wn|dataloader|dataloader1|INF|sorttab|No sort parameters have been specified for : volatilitysurface. Using default parameters
2017.11.20D08:46:12.737827000|wsp18497wn|dataloader|dataloader1|INF|sortfunction|sorting :hdb/2017.09.05/volatilitysurface/ by these columns : sym, time
2017.11.20D08:46:12.753428000|wsp18497wn|dataloader|dataloader1|ERR|sortfunction|failed to sort :hdb/2017.09.05/volatilitysurface/ by these columns : sym, time.  The error was: hdb/2017.09.

J'obtiens l'erreur suivante sorttab|No sort parameters have been specified for : volatilitysurface. Using default parameters où est documenté ce sorttab ? utilise-t-il la table PK par défaut ?

UPDATE3 Ok a corrigé UPDATE2 en fournissant une valeur par défaut de sort.csv sous mon config dossier :

tabname,att,column,sort
default,p,sym,1
default,,time,1
volatilitysurface,,date,1
volatilitysurface,,ccypair,1

Mais maintenant je vois que si j'appelle la fonction plusieurs fois sur les mêmes fichiers, elle ajoute simplement les données dupliquées au lieu de upsert l'ingérer.

UPDATE4 Je n'y suis toujours pas arrivé... en supposant que je puisse vérifier qu'aucun fichier en double n'est utilisé. Lorsque je charge et démarre la base de données, je reçois une structure qui ressemble à une sorte de dictionnaire et non à une table.

2017.10.31| (,`volatilitysurface)!,+`date`ccypair`atm_convention`premium_incl..
2017.11.01| (,`volatilitysurface)!,+`date`ccypair`atm_convention`premium_incl..
2017.11.02| (,`volatilitysurface)!,+`date`ccypair`atm_convention`premium_incl..
2017.11.03| (,`volatilitysurface)!,+`date`ccypair`atm_convention`premium_incl..
sym       | `AUDNOK`AUDCNH`AUDJPY`AUDHKD`AUDCHF`AUDSGD`AUDCAD`AUDDKK`CADSGD`C..

Notez que date est en fait datetime Z et pas seulement date. Ma version complète et la plus récente de l'invocation de la fonction est la suivante :

target:hsym `$("" sv ("./";getenv[`KDBHDB];"/volatilitysurface"));
rawdatadir:hsym `$getenv[`KDBRAWDATA];
.loader.loadallfiles[`headers`types`separator`tablename`dbdir`partitioncol`dataprocessfunc!(`x`ccypair`atm_convention`premium_included`smile_type`vs_type`delta_ratio`delta_setting`wing_extrapolation`spread_type;"ZSSSSSFFFS";enlist ",";`volatilitysurface;target;`date;{[p;t] select date,ccypair,atm_convention,premium_included,smile_type,vs_type,delta_ratio,delta_setting,wing_extrapolation,spread_type from update date:x, premium_included:?[premium_included = `$"true";1b;0b] from t}); rawdatadir];

1voto

Jonathon McMurray Points 1902

L'erreur decast se réfère à une valeur qui n'est pas énumérée.

Je ne vois pas d'énumération ici, les tableaux évasés sur disque doivent avoir des colonnes de symboles énumérées. Par exemple, cela peut être fait avec la ligne suivante, avant d'appeler .Q.dpft

volatilitysurface:.Q.en[afolder;volatilitysurface];

Vous pouvez envisager d'utiliser un exemple de chargeur CSV pour charger vos données. Un tel exemple est inclus dans TorQ, le framework KDB développé par AquaQ Analytics (à titre d'avertissement, je travaille pour AquaQ).

Le cadre est disponible (gratuitement) ici : https://github.com/AquaQAnalytics/TorQ

Le composant spécifique qui vous intéressera probablement est dataloader.q et est documenté ici : http://aquaqanalytics.github.io/TorQ/utilities/#dataloaderq

Ce script s'occupera de tout ce qui est nécessaire, chargement de tous les fichiers, énumération, tri sur le disque, application d'attributs etc. ainsi que de l'utilisation de .Q.fsn pour éviter de manquer de mémoire

1voto

Jonathon McMurray Points 1902

Je vais ajouter une deuxième réponse ici pour essayer d'aborder la question de l'utilisation du chargeur de données de TorQ.

J'aimerais savoir quel résultat vous obtenez après avoir exécuté cette fonction ? Il devrait y avoir des messages de journalisation en sortie, pouvez-vous les afficher ? Par exemple, lorsque j'exécute la fonction :

jmcmurray@homer ~/deploy/TorQ (master) $ q torq.q -procname loader -proctype loader -debug
<torq startup messages removed>
q).loader.loadallfiles[`headers`types`separator`tablename`dbdir`partitioncol`dataprocessfunc!(c;"TSSFJFFJJBS";enlist",";`quotes;`:testdb;`date;{[p;t] select date:.z.d,time:TIME,sym:INSTRUMENT,BID,ASK from t});`:csvtest]
2017.11.17D15:03:20.312336000|homer.aquaq.co.uk|loader|loader|INF|dataloader|**** LOADING :csvtest/tradesandquotes20140421.csv ****
2017.11.17D15:03:20.319110000|homer.aquaq.co.uk|loader|loader|INF|dataloader|reading in data chunk
2017.11.17D15:03:20.339414000|homer.aquaq.co.uk|loader|loader|INF|dataloader|Read 11000 rows
2017.11.17D15:03:20.339463000|homer.aquaq.co.uk|loader|loader|INF|dataloader|processing data
2017.11.17D15:03:20.339519000|homer.aquaq.co.uk|loader|loader|INF|dataloader|Enumerating
2017.11.17D15:03:20.340061000|homer.aquaq.co.uk|loader|loader|INF|dataloader|writing 11000 rows to :testdb/2017.11.17/quotes/
2017.11.17D15:03:20.341669000|homer.aquaq.co.uk|loader|loader|INF|dataloader|**** LOADING :csvtest/tradesandquotes20140422.csv ****
2017.11.17D15:03:20.349606000|homer.aquaq.co.uk|loader|loader|INF|dataloader|reading in data chunk
2017.11.17D15:03:20.370793000|homer.aquaq.co.uk|loader|loader|INF|dataloader|Read 11000 rows
2017.11.17D15:03:20.370858000|homer.aquaq.co.uk|loader|loader|INF|dataloader|processing data
2017.11.17D15:03:20.370911000|homer.aquaq.co.uk|loader|loader|INF|dataloader|Enumerating
2017.11.17D15:03:20.371441000|homer.aquaq.co.uk|loader|loader|INF|dataloader|writing 11000 rows to :testdb/2017.11.17/quotes/
2017.11.17D15:03:20.460118000|homer.aquaq.co.uk|loader|loader|INF|init|retrieving sort settings from :/home/jmcmurray/deploy/TorQ/config/sort.csv
2017.11.17D15:03:20.466690000|homer.aquaq.co.uk|loader|loader|INF|sort|sorting the quotes table
2017.11.17D15:03:20.466763000|homer.aquaq.co.uk|loader|loader|INF|sorttab|No sort parameters have been specified for : quotes. Using default parameters
2017.11.17D15:03:20.466820000|homer.aquaq.co.uk|loader|loader|INF|sortfunction|sorting :testdb/2017.11.17/quotes/ by these columns : sym, time
2017.11.17D15:03:20.527216000|homer.aquaq.co.uk|loader|loader|INF|applyattr|applying p attr to the sym column in :testdb/2017.11.17/quotes/
2017.11.17D15:03:20.535095000|homer.aquaq.co.uk|loader|loader|INF|sort|finished sorting the quotes table

Après tout ça, je peux courir \l testdb et il y a une table appelée "quotes" contenant mes données chargées

Si vous pouvez afficher des messages de journalisation comme ceux-ci, cela pourrait être utile pour voir ce qui se passe.

UPDATE

"Mais je vois maintenant que si j'appelle la fonction plusieurs fois sur les mêmes fichiers, elle ajoute simplement les données dupliquées au lieu de les réinsérer."

Si je comprends bien le problème, il semble que vous ne devriez pas appeler la fonction plusieurs fois sur les mêmes fichiers. Un autre processus dans TorQ pourrait être utile ici, le " avertisseur de fichiers ". Ce processus surveillera un répertoire pour les nouveaux fichiers et les fichiers mis à jour, et peut appeler une fonction sur tous ceux qui apparaissent (vous pouvez donc lui demander d'appeler la fonction de chargement avec chaque nouveau fichier automatiquement). Il dispose d'un certain nombre d'options telles que le déplacement des fichiers après traitement (vous pouvez ainsi "archiver" les CSV chargés).

Notez que l'alerte fichier exige qu'une fonction prenne exactement deux paramètres - le répertoire et le nom du fichier. Cela signifie effectivement que vous aurez besoin d'une fonction "wrapper" autour de la fonction loader, qui prend un dictionnaire et un répertoire. Je ne pense pas que TorQ inclut une fonction similaire à .loader.loadallfiles pour un seul fichier, donc il pourrait être nécessaire de copier le fichier cible dans un répertoire temporaire, exécuter loadallfiles sur ce répertoire et ensuite supprimer le fichier de là avant de charger le suivant.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X