You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

145 lines
4.1KB

  1. #![allow(unused)]
  2. #[macro_use]
  3. extern crate slog;
  4. #[macro_use]
  5. extern crate markets;
  6. use std::io::{self, prelude::*};
  7. use std::fs;
  8. use std::path::{Path, PathBuf};
  9. use std::time::*;
  10. use pretty_toa::ThousandsSep;
  11. use structopt::StructOpt;
  12. use serde::{Serialize, Deserialize};
  13. use slog::Drain;
  14. use chrono::{DateTime, Utc};
  15. use markets::crypto::{Exchange, Ticker, Side};
  16. macro_rules! fatal { ($fmt:expr, $($args:tt)*) => {{
  17. eprintln!($fmt, $($args)*);
  18. std::process::exit(1);
  19. }}}
  20. #[structopt(rename_all="kebab-case")]
  21. #[derive(Debug, StructOpt)]
  22. enum Opt {
  23. /// Filter trades-csv by start,end range and save subset to output-path
  24. Range {
  25. /// Path to CSV file with trades data
  26. #[structopt(short = "f", long = "trades-csv")]
  27. #[structopt(parse(from_os_str))]
  28. trades_csv: PathBuf,
  29. /// Where to save the query results (CSV output)
  30. #[structopt(short = "o", long = "output-path")]
  31. #[structopt(parse(from_os_str))]
  32. output_path: PathBuf,
  33. /// rfc3339 format ("YYYY-MM-DDTHH:MM:SSZ")
  34. start: DateTime<Utc>,
  35. /// rfc3339 format ("YYYY-MM-DDTHH:MM:SSZ")
  36. end: DateTime<Utc>,
  37. },
  38. }
  39. #[derive(Deserialize)]
  40. struct Trade {
  41. /// Unix nanoseconds
  42. pub time: u64,
  43. pub exch: Exchange,
  44. pub ticker: Ticker,
  45. //pub side: Option<Side>,
  46. pub price: f64,
  47. pub amount: f64,
  48. }
  49. fn per_sec(n: usize, span: Duration) -> f64 {
  50. if n == 0 || span < Duration::from_micros(1) { return 0.0 }
  51. let s: f64 = span.as_nanos() as f64 / 1e9f64;
  52. n as f64 / s
  53. }
  54. fn nanos(utc: DateTime<Utc>) -> u64 {
  55. (utc.timestamp() as u64) * 1_000_000_000_u64 + (utc.timestamp_subsec_nanos() as u64)
  56. }
  57. fn run(start: Instant, logger: &slog::Logger) -> Result<usize, String> {
  58. let opt = Opt::from_args();
  59. let mut n = 0;
  60. match opt {
  61. Opt::Range { trades_csv, output_path, start, end } => {
  62. let logger = logger.new(o!("cmd" => "range"));
  63. info!(logger, "beginning range cmd";
  64. "trades_csv" => %trades_csv.display(),
  65. "output_path" => %output_path.display(),
  66. "start" => %start,
  67. "end" => %end,
  68. );
  69. if ! trades_csv.exists() { return Err(format!("--trades-csv path does not exist: {}", trades_csv.display())) }
  70. info!(logger, "opening trades_csv file");
  71. let rdr = fs::File::open(&trades_csv)
  72. .map_err(|e| format!("opening trades csv file failed: {} (tried to open {})", e, trades_csv.display()))?;
  73. let rdr = io::BufReader::new(rdr);
  74. let mut rdr = csv::Reader::from_reader(rdr);
  75. let wtr = fs::File::create(&output_path)
  76. .map_err(|e| format!("opening output file failed: {} (tried to open {} for writing)", e, output_path.display()))?;
  77. let wtr = io::BufWriter::new(wtr);
  78. let mut wtr = csv::Writer::from_writer(wtr);
  79. let headers: csv::ByteRecord = rdr.byte_headers().map_err(|e| format!("failed to parse CSV headers: {}", e))?.clone();
  80. let mut row = csv::ByteRecord::new();
  81. let start_nanos = nanos(start);
  82. let end_nanos = nanos(end);
  83. }
  84. }
  85. Ok(n)
  86. }
  87. fn main() {
  88. let start = Instant::now();
  89. let decorator = slog_term::TermDecorator::new().stdout().force_color().build();
  90. let drain = slog_term::FullFormat::new(decorator).use_utc_timestamp().build().fuse();
  91. let drain = slog_async::Async::new(drain).chan_size(1024 * 64).thread_name("recv".into()).build().fuse();
  92. let logger = slog::Logger::root(drain, o!("version" => structopt::clap::crate_version!()));
  93. match run(start, &logger) {
  94. Ok(n) => {
  95. let took = Instant::now() - start;
  96. info!(logger, "finished in {:?}", took;
  97. "n rows" => %n.thousands_sep(),
  98. "rows/sec" => &((per_sec(n, took) * 100.0).round() / 10.0).thousands_sep(),
  99. );
  100. }
  101. Err(e) => {
  102. crit!(logger, "run failed: {:?}", e);
  103. eprintln!("\n\nError: {}", e);
  104. std::thread::sleep(Duration::from_millis(100));
  105. std::process::exit(1);
  106. }
  107. }
  108. }