Ejemplo n.º 1
0
/* WadArchive::getEntryOffset
 * Returns the file byte offset for [entry]
 *******************************************************************/
uint32_t WadArchive::getEntryOffset(ArchiveEntry* entry)
{
	// Check entry
	if (!checkEntry(entry))
		return 0;

	return (uint32_t)(int)entry->exProp("Offset");
}
Ejemplo n.º 2
0
/* WadArchive::setEntryOffset
 * Sets the file byte offset for [entry]
 *******************************************************************/
void WadArchive::setEntryOffset(ArchiveEntry* entry, uint32_t offset)
{
	// Check entry
	if (!checkEntry(entry))
		return;

	entry->exProp("Offset") = (int)offset;
}
Ejemplo n.º 3
0
void InputMethodManager::load() {
    FCITX_D();

    auto inputMethods = d->addonManager_->addonNames(AddonCategory::InputMethod);
    auto &path = StandardPath::global();
    auto files = path.multiOpenAll(StandardPath::Type::Data, "fcitx5/inputmethod", O_RDONLY, filter::Suffix(".conf"));
    for (const auto &file : files) {
        auto &files = file.second;
        RawConfig config;
        // reverse the order, so we end up parse user file at last.
        for (auto iter = files.rbegin(), end = files.rend(); iter != end; iter++) {
            auto fd = iter->fd();
            readFromIni(config, fd);
        }

        InputMethodInfo imInfo;
        imInfo.load(config);
        InputMethodEntry entry = toInputMethodEntry(imInfo);
        if (checkEntry(entry, inputMethods) && d->entries_.count(entry.uniqueName()) == 0) {
            d->entries_.emplace(std::string(entry.uniqueName()), std::move(entry));
        }
    }
    for (const auto &addonName : inputMethods) {
        auto addonInfo = d->addonManager_->addonInfo(addonName);
        // on request input method should always provides entry with config file
        if (!addonInfo || addonInfo->onRequest()) {
            continue;
        }
        auto engine = static_cast<InputMethodEngine *>(d->addonManager_->addon(addonName));
        if (!engine) {
            continue;
        }
        auto newEntries = engine->listInputMethods();
        for (auto &newEntry : newEntries) {
            // ok we can't let you register something werid.
            if (checkEntry(newEntry, inputMethods) && newEntry.addon() == addonName &&
                d->entries_.count(newEntry.uniqueName()) == 0) {
                d->entries_.emplace(std::string(newEntry.uniqueName()), std::move(newEntry));
            }
        }
    }

    loadConfig();
}
Ejemplo n.º 4
0
/* GZipArchive::renameEntry
 * Renames the entry and set the fname flag
 *******************************************************************/
bool GZipArchive::renameEntry(ArchiveEntry* entry, string name)
{
	// Check entry
	if (!checkEntry(entry))
		return false;

	// Do default rename
	bool ok = Archive::renameEntry(entry, name);
	if (ok) flags |= GZIP_FLG_FNAME;
	return ok;
}
Ejemplo n.º 5
0
/* Archive::removeEntry
 * Removes [entry] from the archive. If [delete_entry] is true, the
 * entry will also be deleted. Returns true if the removal succeeded
 *******************************************************************/
bool Archive::removeEntry(ArchiveEntry* entry, bool delete_entry)
{
	// Abort if read only
	if (read_only)
		return false;

	// Check entry
	if (!checkEntry(entry))
		return false;

	// Check if entry is locked
	if (entry->isLocked())
		return false;

	// Get its directory
	ArchiveTreeNode* dir = entry->getParentDir();

	// Error if entry has no parent directory
	if (!dir)
		return false;

	// Create undo step
	if (UndoRedo::currentlyRecording())
		UndoRedo::currentManager()->recordUndoStep(new EntryCreateDeleteUS(false, entry));

	// Get the entry index
	int index = dir->entryIndex(entry);

	// Announce (before actually removing in case entry is still needed)
	MemChunk mc;
	wxUIntPtr ptr = wxPtrToUInt(entry);
	mc.write(&index, sizeof(int));
	mc.write(&ptr, sizeof(wxUIntPtr));
	announce("entry_removing", mc);

	// Remove it from its directory
	bool ok = dir->removeEntry(index);

	// If it was removed ok
	if (ok)
	{
		// Announce removed
		announce("entry_removed", mc);

		// Delete if necessary
		if (delete_entry)
			delete entry;

		// Update variables etc
		setModified(true);
	}

	return ok;
}
Ejemplo n.º 6
0
/* RffArchive::renameEntry
 * Override of Archive::renameEntry to update namespaces if needed
 * and rename the entry if necessary to be grp-friendly (twelve
 * characters max)
 *******************************************************************/
bool RffArchive::renameEntry(ArchiveEntry* entry, string name) {
	// Check entry
	if (!checkEntry(entry))
		return false;

	// Process name (must be 12 characters max)
	name.Truncate(12);
	if (wad_force_uppercase) name.MakeUpper();

	// Do default rename
	return Archive::renameEntry(entry, name);
}
Ejemplo n.º 7
0
/* Wad2Archive::renameEntry
 * Override of Archive::renameEntry enforce wad2-friendly entry names
 * (16 characters max and uppercase if forced)
 *******************************************************************/
bool Wad2Archive::renameEntry(ArchiveEntry* entry, string name)
{
	// Check entry
	if (!checkEntry(entry))
		return false;

	// Process name (must be 16 characters max, also cut any extension as wad entries don't usually want them)
	wxFileName fn(name);
	name = fn.GetName().Truncate(16);
	if (wad_force_uppercase) name.MakeUpper();

	// Do default rename
	return Archive::renameEntry(entry, name);
}
Ejemplo n.º 8
0
/* ResArchive::renameEntry
 * Override of Archive::renameEntry to update namespaces if needed
 * and rename the entry if necessary to be res-friendly (14 chars max)
 *******************************************************************/
bool ResArchive::renameEntry(ArchiveEntry* entry, string name)
{
	// Check entry
	if (!checkEntry(entry))
		return false;

	// Process name (must be 14 characters max)
	wxFileName fn(name);
	name = fn.GetName().Truncate(14);

	// Do default rename
	return Archive::renameEntry(entry, name);

}
Ejemplo n.º 9
0
/* DatArchive::swapEntries
 * Override of Archive::swapEntries to update namespaces if needed
 *******************************************************************/
bool DatArchive::swapEntries(ArchiveEntry* entry1, ArchiveEntry* entry2)
{
	// Check entries
	if (!checkEntry(entry1) || !checkEntry(entry2))
		return false;

	// Do default swap (force root dir)
	bool ok = Archive::swapEntries(entry1, entry2);

	if (ok)
	{
		// Update namespaces if needed
		if (entry1->getName().Upper().Matches("START*") ||
		        entry1->getName().Upper().Matches("END*") ||
		        entry2->getName().Upper().Matches("START*") ||
		        entry2->getName().Upper().Matches("END*"))
			updateNamespaces();

		return true;
	}
	else
		return false;
}
Ejemplo n.º 10
0
// -----------------------------------------------------------------------------
// Override of Archive::renameEntry to update namespaces if needed and rename
// the entry if necessary to be grp-friendly (twelve characters max)
// -----------------------------------------------------------------------------
bool GrpArchive::renameEntry(ArchiveEntry* entry, const string& name)
{
	// Check entry
	if (!checkEntry(entry))
		return false;

	// Process name (must be 12 characters max)
	auto new_name = name;
	new_name.Truncate(12);
	if (wad_force_uppercase)
		new_name.MakeUpper();

	// Do default rename
	return Archive::renameEntry(entry, new_name);
}
Ejemplo n.º 11
0
/* ADatArchive::detectNamespace
 * Returns the namespace that [entry] is within
 *******************************************************************/
string ADatArchive::detectNamespace(ArchiveEntry* entry) {
	// Check entry
	if (!checkEntry(entry))
		return "global";

	// If the entry is in the root dir, it's in the global namespace
	if (entry->getParentDir() == getRoot())
		return "global";

	// Get the entry's *first* parent directory after root (ie <root>/namespace/)
	ArchiveTreeNode* dir = entry->getParentDir();
	while (dir && dir->getParent() != getRoot())
		dir = (ArchiveTreeNode*)dir->getParent();

	// Namespace is the directory's name (in lowercase)
	if (dir)
		return dir->getName().Lower();
	else
		return "global"; // Error, just return global
}
Ejemplo n.º 12
0
/* DatArchive::moveEntry
 * Override of Archive::moveEntry to update namespaces if needed
 *******************************************************************/
bool DatArchive::moveEntry(ArchiveEntry* entry, unsigned position, ArchiveTreeNode* dir)
{
	// Check entry
	if (!checkEntry(entry))
		return false;

	// Do default move (force root dir)
	bool ok = Archive::moveEntry(entry, position, NULL);

	if (ok)
	{
		// Update namespaces if necessary
		if (entry->getName().Upper().Matches("START*") ||
		        entry->getName().Upper().Matches("END*"))
			updateNamespaces();

		return true;
	}
	else
		return false;
}
Ejemplo n.º 13
0
/* WadArchive::renameEntry
 * Override of Archive::renameEntry to update namespaces if needed
 * and rename the entry if necessary to be wad-friendly (8 characters
 * max and no file extension)
 *******************************************************************/
bool WadArchive::renameEntry(ArchiveEntry* entry, string name)
{
	// Check entry
	if (!checkEntry(entry))
		return false;
	name = processEntryName(name);

	// Do default rename
	bool ok = Archive::renameEntry(entry, name);

	if (ok)
	{
		// Update namespaces if necessary
		if (entry->getName().Upper().Matches("*_START") ||
		        entry->getName().Upper().Matches("*_END"))
			updateNamespaces();

		return true;
	}
	return false;
}
Ejemplo n.º 14
0
/* DatArchive::renameEntry
 * Override of Archive::renameEntry to update namespaces if needed
 *******************************************************************/
bool DatArchive::renameEntry(ArchiveEntry* entry, string name)
{
	// Check entry
	if (!checkEntry(entry))
		return false;

	// Do default rename
	bool ok = Archive::renameEntry(entry, name);

	if (ok)
	{
		// Update namespaces if necessary
		if (entry->getName().Upper().Matches("START*") ||
		        entry->getName().Upper().Matches("END*"))
			updateNamespaces();

		return true;
	}
	else
		return false;
}
Ejemplo n.º 15
0
// -----------------------------------------------------------------------------
// Renames [entry] with [name].
// Returns false if the entry was invalid, true otherwise
// -----------------------------------------------------------------------------
bool Archive::renameEntry(ArchiveEntry* entry, string_view name)
{
	// Abort if read only
	if (read_only_)
		return false;

	// Check entry
	if (!checkEntry(entry))
		return false;

	// Check if entry is locked
	if (entry->isLocked())
		return false;

	// Check for directory
	if (entry->type() == EntryType::folderType())
		return renameDir(dir(entry->path(true)), name);

	// Announce (before actually renaming in case old name is still needed)
	MemChunk  mc;
	int       index = entryIndex(entry);
	wxUIntPtr ptr   = wxPtrToUInt(entry);
	mc.write(&index, sizeof(int));
	mc.write(&ptr, sizeof(wxUIntPtr));
	announce("entry_renaming", mc);

	// Create undo step
	if (UndoRedo::currentlyRecording())
		UndoRedo::currentManager()->recordUndoStep(std::make_unique<EntryRenameUS>(entry, name));

	// Rename the entry
	entry->setName(name);
	entry->formatName(formatDesc());
	entry->setState(ArchiveEntry::State::Modified, true);

	// Announce modification
	entryStateChanged(entry);

	return true;
}
Ejemplo n.º 16
0
/* Archive::entryStateChanged
 * Updates the archive variables and announces if necessary that an
 * entry's state has changed
 *******************************************************************/
void Archive::entryStateChanged(ArchiveEntry* entry)
{
	// Check the entry is valid and part of this archive
	if (!checkEntry(entry))
		return;

	// Get the entry index and announce the change
	MemChunk mc(8);
	wxUIntPtr ptr = wxPtrToUInt(entry);
	uint32_t index = entryIndex(entry);
	mc.write(&index, sizeof(uint32_t));
	mc.write(&ptr, sizeof(wxUIntPtr));
	announce("entry_state_changed", mc);


	// If entry was set to unmodified, don't set the archive to modified
	if (entry->getState() == 0)
		return;

	// Set the archive state to modified
	setModified(true);
}
Ejemplo n.º 17
0
// -----------------------------------------------------------------------------
// Moves [entry] to [position] in [dir].
// If [dir] is null, the root dir is used.
// Returns false if the entry was invalid, true otherwise
// -----------------------------------------------------------------------------
bool Archive::moveEntry(ArchiveEntry* entry, unsigned position, ArchiveTreeNode* dir)
{
	// Abort if read only
	if (read_only_)
		return false;

	// Check the entry
	if (!checkEntry(entry))
		return false;

	// Check if the entry is locked
	if (entry->isLocked())
		return false;

	// Get the entry's current directory
	auto cdir = entry->parentDir();

	// Error if no dir
	if (!cdir)
		return false;

	// If no destination dir specified, use root
	if (!dir)
		dir = &dir_root_;

	// Remove the entry from its current dir
	auto sptr = dir->sharedEntryAt(dir->entryIndex(entry)); // Get a shared pointer so it isn't deleted
	removeEntry(entry);

	// Add it to the destination dir
	addEntry(entry, position, dir);

	// Set modified
	setModified(true);

	// Return success
	return true;
}
Ejemplo n.º 18
0
/* Archive::moveEntry
 * Moves [entry] to [position] in [dir]. If [dir] is NULL, the root
 * dir is used. Returns false if the entry was invalid, true
 * otherwise
 *******************************************************************/
bool Archive::moveEntry(ArchiveEntry* entry, unsigned position, ArchiveTreeNode* dir)
{
	// Abort if read only
	if (read_only)
		return false;

	// Check the entry
	if (!checkEntry(entry))
		return false;

	// Check if the entry is locked
	if (entry->isLocked())
		return false;

	// Get the entry's current directory
	ArchiveTreeNode* cdir = entry->getParentDir();

	// Error if no dir
	if (!cdir)
		return false;

	// If no destination dir specified, use root
	if (!dir)
		dir = dir_root;

	// Remove the entry from its current dir
	removeEntry(entry, false);

	// Add it to the destination dir
	addEntry(entry, position, dir);

	// Set modified
	setModified(true);

	// Return success
	return true;
}
Ejemplo n.º 19
0
/*
 * Verify that the indirect table lookup is valid.
 *
 * Returns "false" if something looks bad.
 */
bool IndirectRefTable::getChecked(IndirectRef iref) const
{
    if (iref == NULL) {
        LOGW("Attempt to look up NULL %s reference", indirectRefKindToString(kind_));
        return false;
    }
    if (indirectRefKind(iref) == kIndirectKindInvalid) {
        LOGE("JNI ERROR (app bug): invalid %s reference %p",
                indirectRefKindToString(kind_), iref);
        abortMaybe();
        return false;
    }

    int topIndex = segmentState.parts.topIndex;
    int idx = extractIndex(iref);
    if (idx >= topIndex) {
        /* bad -- stale reference? */
        LOGE("JNI ERROR (app bug): accessed stale %s reference %p (index %d in a table of size %d)",
                indirectRefKindToString(kind_), iref, idx, topIndex);
        abortMaybe();
        return false;
    }

    if (table_[idx] == NULL) {
        LOGI("JNI ERROR (app bug): accessed deleted %s reference %p",
                indirectRefKindToString(kind_), iref);
        abortMaybe();
        return false;
    }

    if (!checkEntry("use", iref, idx)) {
        return false;
    }

    return true;
}
Ejemplo n.º 20
0
/* DatArchive::removeEntry
 * Override of Archive::removeEntry to update namespaces if needed
 *******************************************************************/
bool DatArchive::removeEntry(ArchiveEntry* entry, bool delete_entry)
{
	// Check entry
	if (!checkEntry(entry))
		return false;

	// Get entry name (for later)
	string name = entry->getName();

	// Do default remove
	bool ok = Archive::removeEntry(entry, delete_entry);

	if (ok)
	{
		// Update namespaces if necessary
		if (name.Upper().Matches("START*") ||
		        name.Upper().Matches("END*"))
			updateNamespaces();

		return true;
	}
	else
		return false;
}
Ejemplo n.º 21
0
/* ZipArchive::getMapInfo
 * Returns the mapdesc_t information about the map at [entry], if
 * [entry] is actually a valid map (ie. a wad archive in the maps
 * folder)
 *******************************************************************/
Archive::mapdesc_t ZipArchive::getMapInfo(ArchiveEntry* entry)
{
	mapdesc_t map;

	// Check entry
	if (!checkEntry(entry))
		return map;

	// Check entry type
	if (entry->getType()->getFormat() != "archive_wad")
		return map;

	// Check entry directory
	if (entry->getParentDir()->getParent() != getRoot() || entry->getParentDir()->getName() != "maps")
		return map;

	// Setup map info
	map.archive = true;
	map.head = entry;
	map.end = entry;
	map.name = entry->getName(true).Upper();

	return map;
}
Ejemplo n.º 22
0
int main(int argc, char** argv) {
  std::cout << "Blackbird Bitcoin Arbitrage" << std::endl;
  std::cout << "DISCLAIMER: USE THE SOFTWARE AT YOUR OWN RISK\n" << std::endl;

  std::locale mylocale("");

  Parameters params("blackbird.conf");

  if (!params.demoMode) {
    if (!params.useFullCash) {
      if (params.cashForTesting < 10.0) {
        std::cout << "WARNING: Minimum test cash recommended: $10.00\n" << std::endl;
      }
      if (params.cashForTesting > params.maxExposure) {
        std::cout << "ERROR: Test cash ($" << params.cashForTesting << ") is above max exposure ($" << params.maxExposure << ")\n" << std::endl;
        return -1;
      }
    }
  }

  getQuoteType getQuote[10];
  getAvailType getAvail[10];
  sendOrderType sendOrder[10];
  isOrderCompleteType isOrderComplete[10];
  getActivePosType getActivePos[10];
  getLimitPriceType getLimitPrice[10];

  int index = 0;
  
  if (params.bitfinexApi.empty() == false || params.demoMode == true) {
    params.addExchange("Bitfinex", params.bitfinexFees, params.bitfinexCanShort, true);
    getQuote[index] = Bitfinex::getQuote;
    getAvail[index] = Bitfinex::getAvail;
    sendOrder[index] = Bitfinex::sendOrder;
    isOrderComplete[index] = Bitfinex::isOrderComplete;
    getActivePos[index] = Bitfinex::getActivePos;
    getLimitPrice[index] = Bitfinex::getLimitPrice;
    index++;
  }
  if (params.okcoinApi.empty() == false || params.demoMode == true) {
    params.addExchange("OKCoin", params.okcoinFees, params.okcoinCanShort, true);
    getQuote[index] = OkCoin::getQuote;
    getAvail[index] = OkCoin::getAvail;
    sendOrder[index] = OkCoin::sendOrder;
    isOrderComplete[index] = OkCoin::isOrderComplete;
    getActivePos[index] = OkCoin::getActivePos;
    getLimitPrice[index] = OkCoin::getLimitPrice;
    index++;
  }
  if (params.bitstampClientId.empty() == false || params.demoMode == true) {
    params.addExchange("Bitstamp", params.bitstampFees, params.bitstampCanShort, true);
    getQuote[index] = Bitstamp::getQuote;
    getAvail[index] = Bitstamp::getAvail;
    sendOrder[index] = Bitstamp::sendOrder;
    isOrderComplete[index] = Bitstamp::isOrderComplete;
    getActivePos[index] = Bitstamp::getActivePos;
    getLimitPrice[index] = Bitstamp::getLimitPrice;
    index++;
  }
  if (params.geminiApi.empty() == false || params.demoMode == true) {
    params.addExchange("Gemini", params.geminiFees, params.geminiCanShort, true);
    getQuote[index] = Gemini::getQuote;
    getAvail[index] = Gemini::getAvail;
    sendOrder[index] = Gemini::sendOrder;
    isOrderComplete[index] = Gemini::isOrderComplete;
    getActivePos[index] = Gemini::getActivePos;
    getLimitPrice[index] = Gemini::getLimitPrice;
    index++;
  }
  if (params.krakenApi.empty() == false || params.demoMode == true) {
    params.addExchange("Kraken", params.krakenFees, params.krakenCanShort, true);
    getQuote[index] = Kraken::getQuote;
    getAvail[index] = Kraken::getAvail;
    sendOrder[index] = Kraken::sendOrder;
    isOrderComplete[index] = Kraken::isOrderComplete;
    getActivePos[index] = Kraken::getActivePos;
    getLimitPrice[index] = Kraken::getLimitPrice;
    index++;
  }
  if (params.itbitApi.empty() == false || params.demoMode == true) {
    params.addExchange("ItBit", params.itbitFees, params.itbitCanShort, false);
    getQuote[index] = ItBit::getQuote;
    getAvail[index] = ItBit::getAvail;
    // sendOrder[index] = ItBit::sendOrder;
    // isOrderComplete[index] = ItBit::isOrderComplete;
    getActivePos[index] = ItBit::getActivePos;
    getLimitPrice[index] = ItBit::getLimitPrice;
    index++;
  }
  if (params.btceApi.empty() == false || params.demoMode == true) {
    params.addExchange("BTC-e", params.btceFees, params.btceCanShort, false);
    getQuote[index] = BTCe::getQuote;
    getAvail[index] = BTCe::getAvail;
    // sendOrder[index] = BTCe::sendOrder;
    // isOrderComplete[index] = BTCe::isOrderComplete;
    getActivePos[index] = BTCe::getActivePos;
    getLimitPrice[index] = BTCe::getLimitPrice;
    index++;
  }
  if (params.sevennintysixApi.empty() == false || params.demoMode == true) {
    params.addExchange("796.com", params.sevennintysixFees, params.sevennintysixCanShort, true);
    getQuote[index] = SevenNintySix::getQuote;
    getAvail[index] = SevenNintySix::getAvail;
    sendOrder[index] = SevenNintySix::sendOrder;
    isOrderComplete[index] = SevenNintySix::isOrderComplete;
    getActivePos[index] = SevenNintySix::getActivePos;
    getLimitPrice[index] = SevenNintySix::getLimitPrice;
    index++;
  }


  if (index < 2) {
    std::cout << "ERROR: Blackbird needs at least two Bitcoin exchanges. Please edit the config.json file to add new exchanges\n" << std::endl;
    return -1;
  }

  std::string currDateTime = printDateTimeFileName();
  std::string csvFileName = "blackbird_result_" + currDateTime + ".csv";
  std::ofstream csvFile;
  csvFile.open(csvFileName.c_str(), std::ofstream::trunc);
  csvFile << "TRADE_ID,EXCHANGE_LONG,EXHANGE_SHORT,ENTRY_TIME,EXIT_TIME,DURATION,TOTAL_EXPOSURE,BALANCE_BEFORE,BALANCE_AFTER,RETURN\n";
  csvFile.flush();

  std::string logFileName = "blackbird_log_" + currDateTime + ".log";
  std::ofstream logFile;
  logFile.open(logFileName.c_str(), std::ofstream::trunc);
  logFile.imbue(mylocale);
  logFile.precision(2);
  logFile << std::fixed;
  params.logFile = &logFile;
  logFile << "--------------------------------------------" << std::endl;
  logFile << "|   Blackbird Bitcoin Arbitrage Log File   |" << std::endl;
  logFile << "--------------------------------------------\n" << std::endl;
  logFile << "Blackbird started on " << printDateTime() << "\n" << std::endl;

  if (params.demoMode) {
    logFile << "Demo mode: trades won't be generated\n" << std::endl;
  }

  std::cout << "Log file generated: " << logFileName << "\nBlackbird is running... (pid " << getpid() << ")\n" << std::endl;

  // Vector of Bitcoin objects
  std::vector<Bitcoin*> btcVec;
  int num_exchange = params.nbExch();
  // create Bitcoin objects
  for (int i = 0; i < num_exchange; ++i) {
    btcVec.push_back(new Bitcoin(i, params.exchName[i], params.fees[i], params.canShort[i], params.isImplemented[i]));
  }
  curl_global_init(CURL_GLOBAL_ALL);
  params.curl = curl_easy_init();

  logFile << "[ Targets ]" << std::endl;
  logFile << "   Spread Entry:  " << params.spreadEntry * 100.0 << "%" << std::endl;
  logFile << "   Spread Target: " << params.spreadTarget * 100.0  << "%" << std::endl;
  if (params.spreadEntry <= 0.0) {
    logFile << "   WARNING: Spread Entry should be positive" << std::endl;
  }
  if (params.spreadTarget <= 0.0) {
    logFile << "   WARNING: Spread Target should be positive" << std::endl;
  }
  logFile << std::endl;
  // store current balances
  logFile << "[ Current balances ]" << std::endl;
  double* balanceUsd = (double*)malloc(sizeof(double) * num_exchange);
  double* balanceBtc = (double*)malloc(sizeof(double) * num_exchange);
  for (int i = 0; i < num_exchange; ++i) {
    if (params.demoMode) {
      balanceUsd[i] = 0.0;
      balanceBtc[i] = 0.0;
    } else {
      balanceUsd[i] = getAvail[i](params, "usd");
      balanceBtc[i] = getAvail[i](params, "btc");
    }
  }
  // contains balances after a completed trade
  double* newBalUsd = (double*)malloc(sizeof(double) * num_exchange);
  double* newBalBtc = (double*)malloc(sizeof(double) * num_exchange);
  memset(newBalUsd, 0.0, sizeof(double) * num_exchange);
  memset(newBalBtc, 0.0, sizeof(double) * num_exchange);

  for (int i = 0; i < num_exchange; ++i) {
    logFile << "   " << params.exchName[i] << ":\t";
    logFile << balanceUsd[i] << " USD\t" << std::setprecision(6) << balanceBtc[i]  << std::setprecision(2) << " BTC" << std::endl;
    if (balanceBtc[i] > 0.0300) {
      logFile << "ERROR: All BTC accounts must be empty before starting Blackbird" << std::endl;
      return -1;
    }
  }
  logFile << std::endl;
  logFile << "[ Cash exposure ]" << std::endl;
  if (params.demoMode) {
    logFile << "   No cash - Demo mode" << std::endl;
  } else {
    if (params.useFullCash) {
      logFile << "   FULL cash used!" << std::endl;
    } else {
      logFile << "   TEST cash used\n   Value: $" << params.cashForTesting << std::endl;
    }
  }
  logFile << std::endl;

  time_t rawtime;
  rawtime = time(NULL);
  struct tm* timeinfo;
  timeinfo = localtime(&rawtime);
  // wait the next gapSec seconds before starting
  time(&rawtime);
  timeinfo = localtime(&rawtime);
  while ((int)timeinfo->tm_sec % params.gapSec != 0) {
    sleep(0.01);
    time(&rawtime);
    timeinfo = localtime(&rawtime);
  }
  // main loop
  if (!params.verbose) {
    logFile << "Running..." << std::endl;
  }
  bool inMarket = false;
  int resultId = 0;
  Result res;
  res.clear();
  unsigned currIteration = 0;
  bool stillRunning = true;
  time_t currTime;
  time_t diffTime;
  while (stillRunning) {

    currTime = mktime(timeinfo);
    time(&rawtime);
    diffTime = difftime(rawtime, currTime);
    // check if we are already too late
    if (diffTime > 0) {
      logFile << "WARNING: " << diffTime << " second(s) too late at " << printDateTime(currTime) << std::endl;
      // unsigned skip = (unsigned)ceil(diffTime / gapSec);
      // go to next iteration
      timeinfo->tm_sec = timeinfo->tm_sec + (ceil(diffTime / params.gapSec) + 1) * params.gapSec;
      currTime = mktime(timeinfo);
      sleep(params.gapSec - (diffTime % params.gapSec));
      logFile << std::endl;
    }
    else if (diffTime < 0) {
      sleep(-difftime(rawtime, currTime));  // sleep until the next iteration
    }
    if (params.verbose) {
      if (!inMarket) {
        logFile << "[ " << printDateTime(currTime) << " ]" << std::endl;
      } else {
        logFile << "[ " << printDateTime(currTime) << " IN MARKET: Long " << res.exchNameLong << " / Short " << res.exchNameShort << " ]" << std::endl;
      }
    }
    for (int e = 0; e < num_exchange; ++e) {
      double bid = getQuote[e](params, true);
      double ask = getQuote[e](params, false);
      if (bid == 0.0) {
        logFile << "   WARNING: " << params.exchName[e] << " bid is null, use previous one" << std::endl;
      }
      if (ask == 0.0) {
        logFile << "   WARNING: " << params.exchName[e] << " ask is null, use previous one" << std::endl;
      }
      if (params.verbose) {
        logFile << "   " << params.exchName[e] << ": \t" << bid << " / " << ask << std::endl;
      }
      btcVec[e]->updateData(bid, ask, 0.0);
      curl_easy_reset(params.curl);
    }
    if (params.verbose) {
      logFile << "   ----------------------------" << std::endl;
    }

    // compute entry point
    if (!inMarket) {
      for (int i = 0; i < num_exchange; ++i) {
        for (int j = 0; j < num_exchange; ++j) {
          if (i != j) {
            if (checkEntry(btcVec[i], btcVec[j], res, params)) {
              // entry opportunity found
              res.exposure = std::min(balanceUsd[res.idExchLong], balanceUsd[res.idExchShort]);
              if (params.demoMode) {
                logFile << "INFO: Opportunity found but no trade will be generated (Demo mode)" << std::endl;
                break;
              }
              if (res.exposure == 0.0) {
                logFile << "WARNING: Opportunity found but no cash available. Trade canceled" << std::endl;
                break;
              }
              if (params.useFullCash == false && res.exposure <= params.cashForTesting) {
                logFile << "WARNING: Opportunity found but no enough cash. Need more than TEST cash (min. $" << params.cashForTesting << "). Trade canceled" << std::endl;
                break;
              }
              if (params.useFullCash) {
                res.exposure -= params.untouchedCash * res.exposure;  // leave untouchedCash
                if (res.exposure > params.maxExposure) {
                  logFile << "WARNING: Opportunity found but exposure ($" << res.exposure << ") above the limit" << std::endl;
                  logFile << "         Max exposure will be used instead ($" << params.maxExposure << ")" << std::endl;
                  res.exposure = params.maxExposure;
                }
              } else {
                res.exposure = params.cashForTesting;  // use test money
              }
              double volumeLong = res.exposure / btcVec[res.idExchLong]->getAsk();
              double volumeShort = res.exposure / btcVec[res.idExchShort]->getBid();
              double limPriceLong = getLimitPrice[res.idExchLong](params, volumeLong, false);
              double limPriceShort = getLimitPrice[res.idExchShort](params, volumeShort, true);
              if (limPriceLong - res.priceLongIn > params.priceDeltaLim || res.priceShortIn - limPriceShort > params.priceDeltaLim) {
                logFile << "WARNING: Opportunity found but not enough liquidity. Trade canceled" << std::endl;
                logFile << "         Target long price:  " << res.priceLongIn << ", Real long price:  " << limPriceLong << std::endl;
                logFile << "         Target short price: " << res.priceShortIn << ", Real short price: " << limPriceShort << std::endl;
                res.trailing[res.idExchLong][res.idExchShort] = -1.0;
                break;
              }
              inMarket = true;
              resultId++;
              // update result
              res.id = resultId;
              res.entryTime = currTime;
              res.printEntry(*params.logFile);
              res.maxSpread[res.idExchLong][res.idExchShort] = -1.0;
              res.minSpread[res.idExchLong][res.idExchShort] = 1.0;
              res.trailing[res.idExchLong][res.idExchShort] = 1.0;
              int longOrderId = 0;
              int shortOrderId = 0;
              // send orders
              longOrderId = sendOrder[res.idExchLong](params, "buy", volumeLong, btcVec[res.idExchLong]->getAsk());
              shortOrderId = sendOrder[res.idExchShort](params, "sell", volumeShort, btcVec[res.idExchShort]->getBid());
              // wait for the orders to be filled
              logFile << "Waiting for the two orders to be filled..." << std::endl;
              sleep(3.0);
              while (!isOrderComplete[res.idExchLong](params, longOrderId) || !isOrderComplete[res.idExchShort](params, shortOrderId)) {
                sleep(3.0);
              }
              logFile << "Done" << std::endl;
              longOrderId = 0;
              shortOrderId = 0;
              break;
            }
          }
        }
        if (inMarket) {
          break;
        }
      }
      if (params.verbose) {
        logFile << std::endl;
      }
    }
    // in market, looking to exit
    else if (inMarket) {
      if (checkExit(btcVec[res.idExchLong], btcVec[res.idExchShort], res, params, currTime)) {
        // exit opportunity found
        // check current exposure
        double* btcUsed = (double*)malloc(sizeof(double) * num_exchange);
        for (int i = 0; i < num_exchange; ++i) {
          btcUsed[i] = getActivePos[i](params);
        }
        double volumeLong = btcUsed[res.idExchLong];
        double volumeShort = btcUsed[res.idExchShort];
        double limPriceLong = getLimitPrice[res.idExchLong](params, volumeLong, true);
        double limPriceShort = getLimitPrice[res.idExchShort](params, volumeShort, false);

        if (res.priceLongOut - limPriceLong > params.priceDeltaLim || limPriceShort - res.priceShortOut > params.priceDeltaLim) {
          logFile << "WARNING: Opportunity found but not enough liquidity. Trade canceled" << std::endl;
          logFile << "         Target long price:  " << res.priceLongOut << ", Real long price:  " << limPriceLong << std::endl;
          logFile << "         Target short price: " << res.priceShortOut << ", Real short price: " << limPriceShort << std::endl;
          res.trailing[res.idExchLong][res.idExchShort] = 1.0;
        } else {
          res.exitTime = currTime;
          res.printExit(*params.logFile);
          int longOrderId = 0;
          int shortOrderId = 0;
          logFile << std::setprecision(6) << "BTC exposure on " << params.exchName[res.idExchLong] << ": " << volumeLong << std::setprecision(2) << std::endl;
          logFile << std::setprecision(6) << "BTC exposure on " << params.exchName[res.idExchShort] << ": " << volumeShort << std::setprecision(2) << std::endl;
          logFile << std::endl;
          // send orders
          longOrderId = sendOrder[res.idExchLong](params, "sell", fabs(btcUsed[res.idExchLong]), btcVec[res.idExchLong]->getBid());
          shortOrderId = sendOrder[res.idExchShort](params, "buy", fabs(btcUsed[res.idExchShort]), btcVec[res.idExchShort]->getAsk());
          // wait for the orders to be filled
          logFile << "Waiting for the two orders to be filled..." << std::endl;
          sleep(3.0);
          while (!isOrderComplete[res.idExchLong](params, longOrderId) || !isOrderComplete[res.idExchShort](params, shortOrderId)) {
            sleep(3.0);
          }
          logFile << "Done\n" << std::endl;
          longOrderId = 0;
          shortOrderId = 0;
          inMarket = false;
          // new balances
          for (int i = 0; i < num_exchange; ++i) {
            newBalUsd[i] = getAvail[i](params, "usd");
            newBalBtc[i] = getAvail[i](params, "btc");
          }
          for (int i = 0; i < num_exchange; ++i) {
            logFile << "New balance on " << params.exchName[i] << ":  \t";
            logFile << newBalUsd[i] << " USD (perf $" << newBalUsd[i] - balanceUsd[i] << "), ";
            logFile << std::setprecision(6) << newBalBtc[i]  << std::setprecision(2) << " BTC" << std::endl;
          }
          logFile << std::endl;
          // update res with total balance
          for (int i = 0; i < num_exchange; ++i) {
            res.befBalUsd += balanceUsd[i];
            res.aftBalUsd += newBalUsd[i];
          }
          // update current balances with new values
          for (int i = 0; i < num_exchange; ++i) {
            balanceUsd[i] = newBalUsd[i];
            balanceBtc[i] = newBalBtc[i];
          }
          logFile << "ACTUAL PERFORMANCE: " << "$" << res.aftBalUsd - res.befBalUsd << " (" << res.totPerf() * 100.0 << "%)\n" << std::endl;
          csvFile << res.id << "," << res.exchNameLong << "," << res.exchNameShort << "," << printDateTimeCsv(res.entryTime) << "," << printDateTimeCsv(res.exitTime);
          csvFile << "," << res.getLength() << "," << res.exposure * 2.0 << "," << res.befBalUsd << "," << res.aftBalUsd << "," << res.totPerf() << "\n";
          csvFile.flush();
          if (params.sendEmail) {
            sendEmail(res, params);
            logFile << "Email sent" << std::endl;
          }
          res.clear();
          std::ifstream infile("stop_after_exit");
          if (infile.good()) {
            logFile << "Exit after last trade (file stop_after_exit found)" << std::endl;
            stillRunning = false;
          }
        }
      }
      if (params.verbose) {
        logFile << std::endl;
      }
    }
    timeinfo->tm_sec = timeinfo->tm_sec + params.gapSec;
    currIteration++;
    if (currIteration >= params.debugMaxIteration) {
      logFile << "Max iteration reached (" << params.debugMaxIteration << ")" <<std::endl;
      stillRunning = false;
    }
  }
  for (int i = 0; i < num_exchange; ++i) {
    delete(btcVec[i]);
  }
  curl_easy_cleanup(params.curl);
  curl_global_cleanup();
  csvFile.close();
  logFile.close();

  return 0;
}
Ejemplo n.º 23
0
DvbEpgDialog::DvbEpgDialog(DvbManager *manager_, QWidget *parent) : KDialog(parent),
	manager(manager_)
{
	setButtons(KDialog::Close);
	setCaption(i18nc("@title:window", "Program Guide"));

	QWidget *widget = new QWidget(this);
	QBoxLayout *mainLayout = new QHBoxLayout(widget);

	epgChannelTableModel = new DvbEpgChannelTableModel(this);
	epgChannelTableModel->setManager(manager);
	channelView = new QTreeView(widget);
	channelView->setMaximumWidth(30 * fontMetrics().averageCharWidth());
	channelView->setModel(epgChannelTableModel);
	channelView->setRootIsDecorated(false);
	channelView->setUniformRowHeights(true);
	connect(channelView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
		this, SLOT(channelActivated(QModelIndex)));
	mainLayout->addWidget(channelView);

	QBoxLayout *rightLayout = new QVBoxLayout();
	QBoxLayout *boxLayout = new QHBoxLayout();

	KAction *scheduleAction = new KAction(QIcon::fromTheme(QLatin1String("media-record")),
		i18nc("@action:inmenu tv show", "Record Show"), this);
	connect(scheduleAction, SIGNAL(triggered()), this, SLOT(scheduleProgram()));

	QPushButton *pushButton =
		new QPushButton(scheduleAction->icon(), scheduleAction->text(), widget);
	connect(pushButton, SIGNAL(clicked()), this, SLOT(scheduleProgram()));
	boxLayout->addWidget(pushButton);

	boxLayout->addWidget(new QLabel(i18nc("@label:textbox", "Search:"), widget));

	epgTableModel = new DvbEpgTableModel(this);
	epgTableModel->setEpgModel(manager->getEpgModel());
	connect(epgTableModel, SIGNAL(layoutChanged()), this, SLOT(checkEntry()));
	KLineEdit *lineEdit = new KLineEdit(widget);
	lineEdit->setClearButtonShown(true);
	connect(lineEdit, SIGNAL(textChanged(QString)),
		epgTableModel, SLOT(setContentFilter(QString)));
	boxLayout->addWidget(lineEdit);
	rightLayout->addLayout(boxLayout);

	epgView = new QTreeView(widget);
	epgView->addAction(scheduleAction);
	epgView->header()->setResizeMode(QHeaderView::ResizeToContents);
	epgView->setContextMenuPolicy(Qt::ActionsContextMenu);
	epgView->setMinimumWidth(75 * fontMetrics().averageCharWidth());
	epgView->setModel(epgTableModel);
	epgView->setRootIsDecorated(false);
	epgView->setUniformRowHeights(true);
	connect(epgView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
		this, SLOT(entryActivated(QModelIndex)));
	rightLayout->addWidget(epgView);

	contentLabel = new QLabel(widget);
	contentLabel->setAlignment(Qt::AlignLeft | Qt::AlignTop);
	contentLabel->setMargin(5);
	contentLabel->setWordWrap(true);

	QScrollArea *scrollArea = new QScrollArea(widget);
	scrollArea->setBackgroundRole(QPalette::Light);
	scrollArea->setMinimumHeight(12 * fontMetrics().height());
	scrollArea->setWidget(contentLabel);
	scrollArea->setWidgetResizable(true);
	rightLayout->addWidget(scrollArea);
	mainLayout->addLayout(rightLayout);
	setMainWidget(widget);
}
Ejemplo n.º 24
0
int main(int argc, char **argv) {

  // header information
  std::cout << "Blackbird Bitcoin Arbitrage\nVersion 0.0.2" << std::endl;
  std::cout << "DISCLAIMER: USE THE SOFTWARE AT YOUR OWN RISK.\n" << std::endl;

  // read the config file (config.json)
  json_error_t error;
  json_t *root = json_load_file("config.json", 0, &error);
  if (!root) {
    std::cout << "ERROR: config.json incorrect (" << error.text << ")\n" << std::endl;
    return 1;
  }
 
  // get config variables
  int gapSec = json_integer_value(json_object_get(root, "GapSec"));
  unsigned  debugMaxIteration = json_integer_value(json_object_get(root, "DebugMaxIteration"));

  bool useFullCash = json_boolean_value(json_object_get(root, "UseFullCash")); 
  double untouchedCash = json_real_value(json_object_get(root, "UntouchedCash"));
  double cashForTesting = json_real_value(json_object_get(root, "CashForTesting"));

  if (!useFullCash && cashForTesting < 15.0) {
    std::cout << "ERROR: Minimum test cash is $15.00.\n" << std::endl;
    return 1;
  }
  
  // function arrays 
  getQuoteType getQuote[] = {Bitfinex::getQuote, OkCoin::getQuote, Bitstamp::getQuote, Kraken::getQuote};
  getAvailType getAvail[] = {Bitfinex::getAvail, OkCoin::getAvail, Bitstamp::getAvail, Kraken::getAvail};
  sendOrderType sendOrder[] = {Bitfinex::sendOrder, OkCoin::sendOrder, Bitstamp::sendOrder};
  isOrderCompleteType isOrderComplete[] = {Bitfinex::isOrderComplete, OkCoin::isOrderComplete, Bitstamp::isOrderComplete};
  getActivePosType getActivePos[] = {Bitfinex::getActivePos, OkCoin::getActivePos, Bitstamp::getActivePos, Kraken::getActivePos};
  getLimitPriceType getLimitPrice[] = {Bitfinex::getLimitPrice, OkCoin::getLimitPrice, Bitstamp::getLimitPrice, Kraken::getLimitPrice};

  // thousand separator
  std::locale mylocale("");
  std::cout.imbue(mylocale);

  // print precision of two digits
  std::cout.precision(2);
  std::cout << std::fixed;

  // create a parameters structure
  Parameters params(root);
  params.addExchange("Bitfinex", 0.0020, true);
  params.addExchange("OKCoin", 0.0020, false);
  params.addExchange("Bitstamp", 0.0025, false);
  params.addExchange("Kraken", 0.0025, true);

  // CSV file
  std::string csvFileName;
  csvFileName = "result_" + printDateTimeFileName() + ".csv";
  std::ofstream csvFile;
  csvFile.open(csvFileName.c_str(), std::ofstream::trunc);
  // CSV header
  csvFile << "TRADE_ID,EXCHANGE_LONG,EXHANGE_SHORT,ENTRY_TIME,EXIT_TIME,DURATION,TOTAL_EXPOSURE,BALANCE_BEFORE,BALANCE_AFTER,RETURN\n";
  csvFile.flush();

  // time structure
  time_t rawtime;
  rawtime = time(NULL);
  struct tm * timeinfo;
  timeinfo = localtime(&rawtime);
  
  bool inMarket = false;
  int resultId = 0;
  Result res;
  res.clear();
  // Vector of Bitcoin
  std::vector<Bitcoin*> btcVec;

  // create Bitcoin objects
  for (unsigned i = 0; i < params.nbExch(); ++i) {
    btcVec.push_back(new Bitcoin(i, params.exchName[i], params.fees[i], params.hasShort[i]));
  }

  // cURL
  CURL* curl;
  curl_global_init(CURL_GLOBAL_ALL);
  curl = curl_easy_init();

  std::cout << "[ Targets ]" << std::endl;
  std::cout << "   Spread to enter: " << params.spreadEntry * 100.0 << "%" << std::endl;
  std::cout << "   Spread to exit: " << params.spreadExit * 100.0  << "%" << std::endl;
  std::cout << std::endl;

  // store current balances
  std::cout << "[ Current balances ]" << std::endl;
  std::vector<double> balanceUsd;
  std::vector<double> balanceBtc;
 
  for (unsigned i = 0; i < params.nbExch(); ++i) {
    balanceUsd.push_back(getAvail[i](curl, params, "usd"));
    balanceBtc.push_back(getAvail[i](curl, params, "btc"));
  }

  // vectors that contains balances after a completed trade
  std::vector<double> newBalUsd(params.nbExch(), 0.0);
  std::vector<double> newBalBtc(params.nbExch(), 0.0);
  
  for (unsigned i = 0; i < params.nbExch(); ++i) {
    std::cout << "   " << params.exchName[i] << ":\t";
    std::cout << balanceUsd[i] << " USD\t" << std::setprecision(6) << balanceBtc[i]  << std::setprecision(2) << " BTC" << std::endl;
  }
  std::cout << std::endl;

  std::cout << "[ Cash exposure ]" << std::endl;
  if (useFullCash) {
    std::cout << "   FULL cash used!" << std::endl;
  } else {
    std::cout << "   TEST cash used\n   Value: $" << cashForTesting << std::endl;
  }
  std::cout << std::endl;

  // wait the next gapSec seconds before starting
  time(&rawtime);
  timeinfo = localtime(&rawtime);
  while ((int)timeinfo->tm_sec % gapSec != 0) {
    sleep(0.01);
    time(&rawtime);
    timeinfo = localtime(&rawtime);
  }

  // main loop
  if (!params.verbose) {
    std::cout << "Running..." << std::endl;  
  }

  unsigned currIteration = 0;
  bool stillRunning = true;
  while (stillRunning) {

    time_t currTime = mktime(timeinfo);
    time(&rawtime);

    // check if we are already too late
    if (difftime(rawtime, currTime) > 0) {
      std::cout << "WARNING: " << difftime(rawtime, currTime) << " second(s) too late at " << printDateTime(currTime) << std::endl;
      unsigned skip = (unsigned)ceil(difftime(rawtime, currTime) / gapSec);
      for (unsigned i = 0; i < skip; ++i) {
        // std::cout << "         Skipped iteration " << printDateTime(currTime) << std::endl;
        for (unsigned e = 0; e < params.nbExch(); ++e) {
          btcVec[e]->addData(currTime, btcVec[e]->getLastBid(), btcVec[e]->getLastAsk(), 0.0);
        }
        // go to next iteration
        timeinfo->tm_sec = timeinfo->tm_sec + gapSec;
        currTime = mktime(timeinfo);
      }
      std::cout << std::endl;
    }
    // wait for the next iteration
    while (difftime(rawtime, currTime) != 0) {
      sleep(0.01);
      time(&rawtime);
    }
    if (params.verbose) {
      if (!inMarket) {
        std::cout << "[ " << printDateTime(currTime) << " ]" << std::endl;
      }
      else {
        std::cout << "[ " << printDateTime(currTime) << " IN MARKET: Long " << res.exchNameLong << " / Short " << res.exchNameShort << " ]" << std::endl;
      }
    }
    // download the exchanges prices
    for (unsigned e = 0; e < params.nbExch(); ++e) {

      double bid = getQuote[e](curl, true);
      double ask = getQuote[e](curl, false);
      
      // add previous price if bid or ask is 0.0
      if (bid == 0.0) {
        bid = btcVec[e]->getLastBid();
	std::cout << "   WARNING: " << params.exchName[e] << " bid is null, use previous one" << std::endl;
      }
      if (ask == 0.0) {
        ask = btcVec[e]->getLastAsk();
	std::cout << "   WARNING: " << params.exchName[e] << " ask is null, use previous one" << std::endl;
      }


      if (params.verbose) {
        std::cout << "   " << params.exchName[e] << ": \t" << bid << " / " << ask << std::endl;
      }
      btcVec[e]->addData(currTime, bid, ask, 0.0);
      curl_easy_reset(curl);
    }
    // load data terminated
    if (params.verbose) {
      std::cout << "   ----------------------------" << std::endl;
    }
    // compute entry point
    if (!inMarket) {
      for (unsigned i = 0; i < params.nbExch(); ++i) {
        for (unsigned j = 0; j < params.nbExch(); ++j) {
          if (i != j) {
            if (checkEntry(btcVec[i], btcVec[j], res, params)) {
              // entry opportunity found
              // compute exposure
              res.exposure = std::min(balanceUsd[res.idExchLong], balanceUsd[res.idExchShort]);
              if (res.exposure == 0.0) {
                std::cout << "   WARNING: Opportunity found but no cash available. Trade canceled." << std::endl;
                break;
              }
              if (useFullCash == false && res.exposure <= cashForTesting) {
                std::cout << "   WARNING: Opportunity found but no enough cash. Need more than TEST cash (min. $" << cashForTesting << "). Trade canceled." << std::endl;
                break;        
              }

              if (useFullCash) {
                // leave untouchedCash
                res.exposure -= untouchedCash * res.exposure;
              }
              else {
	        // use test money
                res.exposure = cashForTesting;
              }

	      // check volumes
	      double volumeLong = res.exposure / btcVec[res.idExchLong]->getLastAsk();
	      double volumeShort = res.exposure / btcVec[res.idExchShort]->getLastBid();
	      double limPriceLong = getLimitPrice[res.idExchLong](curl, volumeLong, false);	
	      double limPriceShort = getLimitPrice[res.idExchShort](curl, volumeShort, true);
	      
	      if (limPriceLong - res.priceLongIn > 0.30 || res.priceShortIn - limPriceShort > 0.30) {
                std::cout << "   WARNING: Opportunity found but not enough volume. Trade canceled." << std::endl;
		break;
	      }

              inMarket = true;
              resultId++;
              // update result
              res.id = resultId;
              res.entryTime = currTime;
              res.printEntry();
              res.maxSpread[res.idExchLong][res.idExchShort] = -1.0;
              res.minSpread[res.idExchLong][res.idExchShort] = 1.0;
              int longOrderId = 0;
              int shortOrderId = 0;

              // send Long order
              longOrderId = sendOrder[res.idExchLong](curl, params, "buy", volumeLong, btcVec[res.idExchLong]->getLastAsk());
              // send Short order
              shortOrderId = sendOrder[res.idExchShort](curl, params, "sell", volumeShort, btcVec[res.idExchShort]->getLastBid());
              
              // wait for the orders to be filled
              sleep(3.0);
              std::cout << "Waiting for the two orders to be filled..." << std::endl;
              while (!isOrderComplete[res.idExchLong](curl, params, longOrderId) || !isOrderComplete[res.idExchShort](curl, params, shortOrderId)) {
                sleep(3.0);
              }
              std::cout << "Done" << std::endl;
              longOrderId = 0;
              shortOrderId = 0;
              break;
            }
          }
        }
        if (inMarket) {
          break;
        }
      }
      if (params.verbose) {
        std::cout << std::endl;
      }
    }
    // in market, looking to exit
    else if (inMarket) {

      if (checkExit(btcVec[res.idExchLong], btcVec[res.idExchShort], res, params, currTime)) {
        // exit opportunity found


        // check current exposure
        std::vector<double> btcUsed;
        for (unsigned i = 0; i < params.nbExch(); ++i) {
          btcUsed.push_back(getActivePos[i](curl, params));
        }  
       
        // check volumes
	double volumeLong = btcUsed[res.idExchLong];
	double volumeShort = btcUsed[res.idExchShort];
        double limPriceLong = getLimitPrice[res.idExchLong](curl, volumeLong, true);
        double limPriceShort = getLimitPrice[res.idExchShort](curl, volumeShort, false);
        if (res.priceLongOut - limPriceLong > 0.30 || limPriceShort - res.priceShortOut > 0.30) {
          std::cout << "   WARNING: Opportunity found but not enough volume. Trade canceled." << std::endl;
	} else {
	  res.exitTime = currTime;
          res.printExit();
          // send orders
          int longOrderId = 0;
          int shortOrderId = 0;
          std::cout << std::setprecision(6) << "BTC exposure on " << params.exchName[res.idExchLong] << ": " << volumeLong << std::setprecision(2) << std::endl;
          std::cout << std::setprecision(6) << "BTC exposure on " << params.exchName[res.idExchShort] << ": " << volumeShort << std::setprecision(2) << std::endl;
          std::cout << std::endl;
        
          // Close Long
          longOrderId = sendOrder[res.idExchLong](curl, params, "sell", fabs(btcUsed[res.idExchLong]), btcVec[res.idExchLong]->getLastBid());
          // Close Short
          shortOrderId = sendOrder[res.idExchShort](curl, params, "buy", fabs(btcUsed[res.idExchShort]), btcVec[res.idExchShort]->getLastAsk());
        
          // wait for the orders to be filled
          sleep(3.0);
          std::cout << "Waiting for the two orders to be filled..." << std::endl;
          while (!isOrderComplete[res.idExchLong](curl, params, longOrderId) || !isOrderComplete[res.idExchShort](curl, params, shortOrderId)) {
            sleep(3.0);
          }
          std::cout << "Done\n" << std::endl;
          longOrderId = 0;
          shortOrderId = 0;

          // market exited
          inMarket = false;
        
          // new balances
          for (unsigned i = 0; i < params.nbExch(); ++i) {
            newBalUsd[i] = getAvail[i](curl, params, "usd");
            newBalBtc[i] = getAvail[i](curl, params, "btc");
          }
        
          for (unsigned i = 0; i < params.nbExch(); ++i) {
            std::cout << "New balance on " << params.exchName[i] << ":  \t";
            std::cout << newBalUsd[i] << " USD (perf $" << newBalUsd[i] - balanceUsd[i] << "), ";
            std::cout << std::setprecision(6) << newBalBtc[i]  << std::setprecision(2) << " BTC" << std::endl;
          }
          std::cout << std::endl;

          // update res with total balance
          res.befBalUsd = std::accumulate(balanceUsd.begin(), balanceUsd.end(), 0.0);
          res.aftBalUsd = std::accumulate(newBalUsd.begin(), newBalUsd.end(), 0.0);

          // update current balances with new values
          for (unsigned i = 0; i < params.nbExch(); ++i) {
            balanceUsd[i] = newBalUsd[i];
            balanceBtc[i] = newBalBtc[i];
          }

          // display performance
          std::cout << "ACTUAL PERFORMANCE: " << "$" << res.aftBalUsd - res.befBalUsd << " (" << res.totPerf() * 100.0 << "%)\n" << std::endl; 
        
          // new csv line with result
          csvFile << res.id << "," << res.exchNameLong << "," << res.exchNameShort << "," << printDateTimeCsv(res.entryTime) << "," << printDateTimeCsv(res.exitTime);
          csvFile << "," << res.getLength() << "," << res.exposure * 2.0 << "," << res.befBalUsd << "," << res.aftBalUsd << "," << res.totPerf() << "\n";
          csvFile.flush();

          // send email
          if (params.sendEmail) {
            sendEmail(res, params);
            std::cout << "Email sent" << std::endl;
          }

          // delete result information
          res.clear();
        
          // if "stop_after_exit" file exists then return
          std::ifstream infile("stop_after_exit");
          if (infile.good()) {
            std::cout << "Exit after last trade (file stop_after_exit found)" << std::endl;
            stillRunning = false;
          }
        }
      }
      if (params.verbose) {
        std::cout << std::endl;
      }
    }
    // activities for this iteration terminated
    timeinfo->tm_sec = timeinfo->tm_sec + gapSec;
    currIteration++;
    if (currIteration >= debugMaxIteration) {
      std::cout << "Max iteration reached (" << debugMaxIteration << ")" <<std::endl;
      stillRunning = false;
    }
  }
  // delete Bitcoin objects
  for (unsigned i = 0; i < params.nbExch(); ++i) {
    delete(btcVec[i]);
  }
  json_decref(root);
  // close cURL
  curl_easy_cleanup(curl);
  curl_global_cleanup();
  // close csv file
  csvFile.close();
  
  return 0;
}
Ejemplo n.º 25
0
Path findProjectRoot(const Path &path)
{
    assert(path.isAbsolute());
    const Path config = findAncestor(path, ".rtags-config", Shallow);
    if (config.isDir()) {
        const List<String> conf = Path(config + ".rtags-config").readAll().split('\n');
        for (List<String>::const_iterator it = conf.begin(); it != conf.end(); ++it) {
            const char *ch = it->constData();
            while (*ch && isspace(*ch))
                ++ch;
            if (*ch && !strncmp("project: ", ch, 9)) {
                ch += 9;
                while (*ch && isspace(*ch))
                    ++ch;
                const Path p = ch;
                if (p.isDir()) {
                    return p.ensureTrailingSlash();
                } else {
                    error("Invalid project root %s", p.constData());
                }
            }
        }
    }

    static const Path home = Path::home();
    const Entry before[] = {
        { "GTAGS", 0 },
        { "CMakeLists.txt", 0 },
        { "configure", 0 },
        { ".git", 0 },
        { ".svn", 0 },
        { "*.pro", Wildcard },
        { "scons.1", 0 },
        { "*.scons", Wildcard },
        { "SConstruct", 0 },
        { "autogen.*", Wildcard },
        { "GNUMakefile*", Wildcard },
        { "INSTALL*", Wildcard },
        { "README*", Wildcard },
        { 0, 0 }
    };
    {
        const Path ret = checkEntry(before, path, home);
        if (!ret.isEmpty())
            return ret;
    }
    {
        const Path configStatus = findAncestor(path, "config.status", 0);
        if (!configStatus.isEmpty()) {
            FILE *f = fopen((configStatus + "config.status").constData(), "r");
            Path ret;
            if (f) {
                char line[1024];
                enum { MaxLines = 10 };
                for (int i=0; i<MaxLines; ++i) {
                    int r = Rct::readLine(f, line, sizeof(line));
                    if (r == -1)
                        break;
                    char *configure = strstr(line, "/configure ");
                    if (configure) {
                        char *end = configure + 10;
                        while (--configure >= line) {
                            Path conf(configure, end - configure);
                            if (!conf.isAbsolute())
                                conf.resolve();
                            if (conf.isFile()) {
                                ret = conf.parentDir();
                                if (ret == home)
                                    ret.clear();
                                break;
                            }
                        }
                    }
                    if (!ret.isEmpty())
                        break;
                }
                fclose(f);
                if (!ret.isEmpty())
                    return ret;
            }
        }
    }
    {
        const Path cmakeCache = findAncestor(path, "CMakeCache.txt", 0);
        if (!cmakeCache.isEmpty()) {
            FILE *f = fopen((cmakeCache + "Makefile").constData(), "r");
            if (f) {
                Path ret;
                char line[1024];
                enum { MaxLines = 256 };
                for (int i=0; i<MaxLines; ++i) {
                    int r = Rct::readLine(f, line, sizeof(line));
                    if (r == -1) {
                        break;
                    }
                    if (!strncmp(line, "CMAKE_SOURCE_DIR", 16)) {
                        char *dir = line + 16;
                        while (*dir && (*dir == ' ' || *dir == '='))
                            ++dir;
                        if (dir != home) {
                            ret = dir;
                            ret += '/';
                            if (!Path(ret + "CMakeLists.txt").isFile())
                                ret.clear();
                        }
                        break;
                    }
                }
                fclose(f);
                if (!ret.isEmpty())
                    return ret;
            }
        }
    }
    const Entry after[] = {
        { "Makefile*", Wildcard },
        { 0, 0 }
    };

    {
        const Path ret = checkEntry(after, path, home);
        if (!ret.isEmpty())
            return ret;
    }

    return Path();
}
Ejemplo n.º 26
0
/*
 * Remove "obj" from "pRef".  We extract the table offset bits from "iref"
 * and zap the corresponding entry, leaving a hole if it's not at the top.
 *
 * If the entry is not between the current top index and the bottom index
 * specified by the cookie, we don't remove anything.  This is the behavior
 * required by JNI's DeleteLocalRef function.
 *
 * Note this is NOT called when a local frame is popped.  This is only used
 * for explicit single removals.
 *
 * Returns "false" if nothing was removed.
 */
bool IndirectRefTable::remove(u4 cookie, IndirectRef iref)
{
    IRTSegmentState prevState;
    prevState.all = cookie;
    int topIndex = segmentState.parts.topIndex;
    int bottomIndex = prevState.parts.topIndex;

    assert(table_ != NULL);
    assert(alloc_entries_ <= max_entries_);
    assert(segmentState.parts.numHoles >= prevState.parts.numHoles);

    int idx = extractIndex(iref);
    bool workAroundAppJniBugs = false;

    if (indirectRefKind(iref) == kIndirectKindInvalid && gDvmJni.workAroundAppJniBugs) {
        idx = linearScan(iref, bottomIndex, topIndex, table_);
        workAroundAppJniBugs = true;
        if (idx == -1) {
            LOGW("trying to work around app JNI bugs, but didn't find %p in table!", iref);
            return false;
        }
    }

    if (idx < bottomIndex) {
        /* wrong segment */
        LOGV("Attempt to remove index outside index area (%d vs %d-%d)",
            idx, bottomIndex, topIndex);
        return false;
    }
    if (idx >= topIndex) {
        /* bad -- stale reference? */
        LOGD("Attempt to remove invalid index %d (bottom=%d top=%d)",
            idx, bottomIndex, topIndex);
        return false;
    }

    if (idx == topIndex-1) {
        // Top-most entry.  Scan up and consume holes.

        if (workAroundAppJniBugs == false && !checkEntry("remove", iref, idx)) {
            return false;
        }

        table_[idx] = NULL;
        int numHoles = segmentState.parts.numHoles - prevState.parts.numHoles;
        if (numHoles != 0) {
            while (--topIndex > bottomIndex && numHoles != 0) {
                LOGV("+++ checking for hole at %d (cookie=0x%08x) val=%p",
                    topIndex-1, cookie, table_[topIndex-1]);
                if (table_[topIndex-1] != NULL) {
                    break;
                }
                LOGV("+++ ate hole at %d", topIndex-1);
                numHoles--;
            }
            segmentState.parts.numHoles = numHoles + prevState.parts.numHoles;
            segmentState.parts.topIndex = topIndex;
        } else {
            segmentState.parts.topIndex = topIndex-1;
            LOGV("+++ ate last entry %d", topIndex-1);
        }
    } else {
        /*
         * Not the top-most entry.  This creates a hole.  We NULL out the
         * entry to prevent somebody from deleting it twice and screwing up
         * the hole count.
         */
        if (table_[idx] == NULL) {
            LOGV("--- WEIRD: removing null entry %d", idx);
            return false;
        }
        if (workAroundAppJniBugs == false && !checkEntry("remove", iref, idx)) {
            return false;
        }

        table_[idx] = NULL;
        segmentState.parts.numHoles++;
        LOGV("+++ left hole at %d, holes=%d", idx, segmentState.parts.numHoles);
    }

    return true;
}
Ejemplo n.º 27
0
void AppSettings::cmdOk_Click(){

    if (!checkEntry(txtTarBin->text(), "tar"))
        return;

    if (!checkEntry(txtMountBin->text(), "mount"))
        return;

    if (!checkEntry(txtUmountBin->text(), "umount"))
        return;

    if (!checkEntry(txtSudoBin->text(), "sudo"))
        return;

    if (!checkEntry(txtGuiSudoBin->text(), "gui_sudo"))
        return;

    if (!checkEntry(txtUmountBin->text(), "nice"))
        return;

    if (!checkEntry(txtUmountBin->text(), "renice"))
        return;

    if (!checkEntry(txtUmountBin->text(), "sh"))
        return;

    if (!checkEntry(txtConsoleBin->text(), "console"))
        return;

#ifdef WITH_ICOUTILS
    if (!checkEntry(txtWrestoolBin->text(), "wrestool"))
        return;

    if (!checkEntry(txtIcotoolBin->text(), "icotool"))
        return;
#endif

    if (comboProxyType->currentText()!=tr("No Proxy")){
        if (txtProxyHost->text().isEmpty()){
            QMessageBox::warning(this, tr("Error"), tr("Sorry, specify proxy host."));
            return;
        }
        if (txtProxyPort->text().isEmpty()){
            QMessageBox::warning(this, tr("Error"), tr("Sorry, specify proxy port."));
            return;
        }
    }

    QSettings settings(APP_SHORT_NAME, "default");

    settings.beginGroup("logging");
    if (cbClearLogs->checkState()==Qt::Checked) {
        settings.setValue("autoClear", 1);
    } else {
        settings.setValue("autoClear", 0);
    }
    settings.endGroup();

    settings.beginGroup("app");

    if (comboAppIcons->currentText() == tr("Ambient Light")){
        settings.setValue("icon", "q4wine-ambiance");
    } else if (comboAppIcons->currentText() == tr("Ambient Dark")){
        settings.setValue("icon", "q4wine-ambiance-dark");
    } else {
        settings.setValue("icon", "q4wine");
    }

    if (cbShowTray->checkState()==Qt::Checked) {
        settings.setValue("showTrareyIcon", 1);
    } else {
        settings.setValue("showTrareyIcon", 0);
    }

    if (cbMinimizeToTray->checkState()==Qt::Checked) {
        settings.setValue("minimizeToTray", 1);
    } else {
        settings.setValue("minimizeToTray", 0);
    }

    if (cbMinimizeToTrayApp->checkState()==Qt::Checked) {
        settings.setValue("minimizeToTrayAtAppStart", 1);
    } else {
        settings.setValue("minimizeToTrayAtAppStart", 0);
    }

    if (cbShowNotifications->checkState()==Qt::Checked) {
        settings.setValue("showNotifications", 1);
    } else {
        settings.setValue("showNotifications", 0);
    }

    if (comboLangs->currentText()==tr("System Default")){
        settings.setValue("lang", "");
    } else {
        settings.setValue("lang", lng_hash[comboLangs->currentText()]);
    }

    settings.endGroup();
    settings.beginGroup("system");
    settings.setValue("tar", txtTarBin->text());
    settings.setValue("mount", txtMountBin->text());
    settings.setValue("umount", txtUmountBin->text());
    settings.setValue("sudo", txtSudoBin->text());
    settings.setValue("gui_sudo", txtGuiSudoBin->text());
    settings.setValue("nice", txtNiceBin->text());
    settings.setValue("renice", txtReniceBin->text());
    settings.setValue("sh", txtShBin->text());
    settings.endGroup();

    settings.beginGroup("console");
    settings.setValue("bin", txtConsoleBin->text());
    settings.setValue("args", txtConsoleArgs->text());
    settings.endGroup();
#ifdef WITH_ICOUTILS
    settings.beginGroup("icotool");
    settings.setValue("wrestool", txtWrestoolBin->text());
    settings.setValue("icotool", txtIcotoolBin->text());
    settings.endGroup();
#endif

    settings.beginGroup("quickmount");

    settings.setValue("type", this->comboMountProfiles->currentIndex());
    settings.setValue("mount_drive_string", txtMountString->text());
    settings.setValue("mount_image_string", txtMountImageString->text());
    settings.setValue("umount_string", txtUmountString->text());

    settings.endGroup();

    settings.beginGroup("network");
    settings.setValue("host", txtProxyHost->text());
    settings.setValue("port", txtProxyPort->text());
    settings.setValue("user", txtProxyUser->text());
    settings.setValue("pass", txtProxyPass->text());
    if (comboProxyType->currentText()==tr("No Proxy")){
        settings.setValue("type", 0);
    } else {
        if (comboProxyType->currentText()=="HTTP"){
            settings.setValue("type", 1);
        } else {
            settings.setValue("type", 2);
        }
    }

    settings.endGroup();

    settings.beginGroup("advanced");
    settings.setValue("prefixDefaultPath", txtDefPrefixPath->text());
    if (cbOpenRunDialog->isChecked()){
        settings.setValue("openRunDialog", 1);
    } else {
        settings.setValue("openRunDialog", 0);
    }

    if (cbUseSingleClick->isChecked()){
        settings.setValue("useSingleClick", 1);
    } else {
        settings.setValue("useSingleClick", 0);
    }

#if QT_VERSION >= 0x040500
    if (cbUseNativeDialog->isChecked()){
        settings.setValue("useNativeFileDialog", 1);
    } else {
        settings.setValue("useNativeFileDialog", 0);
    }
#endif

    QString desktopSize=cboxDesktopSize->currentText();
    if (desktopSize==tr("No virtual desktop"))
        desktopSize="";

    settings.setValue("defaultDesktopSize", desktopSize);

    settings.endGroup();

    settings.beginGroup("DesktopImport");
    if (cbRemoveDesktopFiles->isChecked()){
        settings.setValue("remove", 1);
    } else {
        settings.setValue("remove", 0);
    }

    if (cbImportDesktopFilesAtStartup->isChecked()){
        settings.setValue("importAtStartup", 1);
    } else {
        settings.setValue("importAtStartup", 0);
    }
    settings.endGroup();

    settings.beginGroup("AppDB");
    if (cbUseSystemBrowser->isChecked()){
        settings.setValue("useSystemBrowser", 1);
    } else {
        settings.setValue("useSystemBrowser", 0);
    }
    settings.endGroup();
#ifndef _OS_DARWIN_
    settings.beginGroup("Plugins");
    if (cbEnableDesktopMenu->isChecked()){
        settings.setValue("enableMenuDesktop", 1);
    } else {
        settings.setValue("enableMenuDesktop", 0);
    }
    settings.endGroup();
#endif

    accept();
    return;
}