Skip to content

Instantly share code, notes, and snippets.

@gourytch
Last active May 21, 2017 14:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gourytch/e5a657303eb0fc52985e0270ba83f555 to your computer and use it in GitHub Desktop.
Save gourytch/e5a657303eb0fc52985e0270ba83f555 to your computer and use it in GitHub Desktop.
HashFlare calculator: nodejs version
/*
* поиск оптимальной стратегии реинвестирования
* исходя из параметров майнера и наивной модели
* с зафиксированной стоимостью фалюты
* с неизменным значением ежедневной прибыльности
* и неизменяющейся вычислительной мощностью Сети
*/
let verbose = false;
// (сэмпл-данные для HashFlare на 20170521)
let btcprice = 1983.667; // текущий курс биткойна в HF (20170521)
let hf_power = 5170; // мощность в GH/s
let hf_income = 0.00215363 / hf_power; // удельная выручка
let hf_fee = 0.00035 / btcprice; // удельная плата за обслуживание
let hf_proficiency = hf_income - hf_fee; // удельная прибыль
let hf_qsize = 10; // кратность покупки мощности (10 GH/s)
let hf_qprice = 1.20 / btcprice; // стоимость минимальной покупки
let Q_hf = { // параметры клаудмайнера
name: "HashFlare",
size: hf_qsize, // минимальный размер объёма закупаемой мощности
price: hf_qprice / hf_qsize, // удельная стоимость единицы мощности
/// в BTC (далее все расчёты - в BTC)
daily: hf_proficiency // удельная дневная выручка
// на единицу мощности (не на квант!)
};
////////////////////////////////////////////////////////////////////////////
function LogClear() {
if (typeof $ !== 'undefined') {
$('#log').text('');
}
}
function Log(s) {
if (typeof $ !== 'undefined') {
$('#log').text($('#log').text() + s + '\n');
} else {
console.log(s);
}
}
function VLog(s) {
if (!verbose) return;
Log(s);
}
/*
* моделирование ежедневной работы
* вход:
* Q - параметры клаудмайнера
* power0 - начальное значение мощностей
* total_days - общее количество дней симуляции
* reinvest_days - количество дней для реинвестирования
*/
function simulate(Q, power0, total_days, reinvest_days) {
let power = power0;
let amount = 0;
let reinvested = 0;
let qprice = Q.size * Q.price; // стоимость кванта мощности
for (day = 0; day < total_days; day++) {
amount += power * Q.daily; // добавили заработанное нашими мощностями
// за предыдущий день
if (day < reinvest_days) {
let quants_to_buy = Math.floor(amount / qprice); // покупка только
// целыми квантами!
if (quants_to_buy > 0) {
let s = quants_to_buy * qprice;
let qp = quants_to_buy * Q.size;
reinvested += s; // сумму реинвестированного учитываем
amount -= s; // оплату снимаем ...
power += qp; // ... мощность наращиваем
VLog("day " + day + ": bought power " + qp +
" for " + s.toFixed(8) +
", now power=" + power + ", amount=" + amount.toFixed(8));
}
}
}
let pprice0 = Q.price * power0;
let pprice = Q.price * power;
let retratio = (amount - pprice0) / pprice0;
return {
Q: Q,
days: total_days,
rdays: reinvest_days,
power0: power0,
power: power,
pprice0: pprice0,
pprice: pprice,
daily: power * Q.daily,
amount: amount,
ramount: reinvested,
retratio: retratio
};
}
/*
* выведем результаты эксперимента
*/
function showResults(R) {
Log("=== Miner : " + R.Q.name + " ===");
Log("parameters:");
Log(" quantum size : " + R.Q.size);
Log(" specific price : " + R.Q.price.toFixed(8) +
" ($" + (R.Q.price * btcprice).toFixed(6) + ")");
Log(" specific proficiency : " + R.Q.daily.toFixed(10) +
" ($" + (R.Q.daily * btcprice).toFixed(10) + ")");
Log("Initial state:")
Log(" power : " + R.power0.toFixed(2));
Log(" invested : " + R.pprice0.toFixed(8) +
" ($" + (R.pprice0 * btcprice).toFixed(2) + ")");
Log(" days to run : " + R.days +
" (" + (R.days / 365).toFixed(1) + " yr)");
Log(" days to reinvest : " + R.rdays +
" (" + (R.rdays / 365).toFixed(1) + " yr)");
Log("Result:")
Log(" final power : " + R.power +
" (" + (R.power * 100 / R.power0).toFixed(2) + "%)");
Log(" reinvested amount : " + R.ramount.toFixed(8));
Log(" final power price : " + R.pprice.toFixed(8) +
" ($" + (R.pprice * btcprice).toFixed(2) + ")");
Log(" final amount : " + R.amount.toFixed(8) +
" ($" + (R.amount * btcprice).toFixed(2) + ")");
Log(" daily netto : " + R.daily.toFixed(8) +
" ($" + (R.daily * btcprice).toFixed(4) + ")");
Log(" monthly income : " + (30 * R.daily).toFixed(8) +
" ($" + (30 * R.daily * btcprice).toFixed(2) + ")");
Log(" proficiency ratio : " + (100 * R.retratio).toFixed(2) + "%");
}
// ищем количество дней реинвестирования
// для максимизации конечного значения на счету
function searchForRich(Q, power0, total_days) {
let Dbest = 0;
let Rbest = simulate(Q, power0, total_days, Dbest);
for (rdays = 1; rdays < total_days; rdays++) {
let Rcur = simulate(Q, power0, total_days, rdays);
if (Rbest.amount < Rcur.amount) {
Dbest = rdays;
Rbest = Rcur;
}
}
return Rbest;
}
// ищем количество дней реинвестирования для желаемой скорости добычи
function searchForIncome(Q, power0, income) {
for (let rdays = 1; true; rdays++) {
let Rcur = simulate(Q, power0, rdays, rdays);
if (income <= Rcur.daily) {
return Rcur;
}
}
}
// ищем минимальное количество дней для добычи желаемого количества
function searchForAmount(Q, power0, amount) {
let Ld = 1
let Lr = searchForRich(Q, power0, Ld)
if (amount < Lr.amount) return Lr;
let Rd = 1000
let Rr = searchForRich(Q, power0, Rd)
if (Rr.amount < amount) return Rr; // Actually, NOT FOUND!
let Md;
let Mr;
while ((Rd-Ld) > 1) {
Md = Math.floor((Ld + Rd) / 2);
if (Md == Ld) Md++;
Mr = searchForRich(Q, power0, Md);
/*
Log("+++ searchForAmount. ["+Ld+".."+Rd+
"]/["+Lr.amount.toFixed(8)+".."+Rr.amount.toFixed(8)+
"], "+Md+ "/" + Mr.amount.toFixed(8));
*/
if (Mr.amount < amount) {
Ld = Md;
Lr = Mr;
} else {
Rd = Md;
Rr = Mr;
}
}
return Rr;
}
LogClear();
let invested = 1000 / btcprice;
// let days = 1000; // успеть до халвинга
let days = 365 * 3; // на три года
hf_power = Math.floor(invested / Q_hf.price / Q_hf.size) * Q_hf.size;
//Log("invested=" + invested.toFixed(8));
//Log("hf_power=" + hf_power.toFixed(2));
//Log("gm_power=" + gm_power.toFixed(2));
// показ лога реинвестирования для hashflare
// verbose=true; showResults(simulate(Q_hf, hf_power, 600, 600));
// простая покупка мощности без реинвеста
Log("=== JUST "+ days+ " DAYS WITHOUT REINVEST ===")
showResults(simulate(Q_hf, hf_power, days, 0));
// оптимизация по конечному значению в пула
// showResults(searchForRich(Q_hf, hf_power, days));
// достижение желаемого размера ежедневной чистой прибыли
// hf_power = 2000;
// let income = 100.0 / btcprice; // 1 USD per day
// let income = 0.01;
// showResults(searchForIncome(Q_hf, hf_power, income));
// время быстрейшего возврата вложенного
//verbose=true
Log("=== RETURN TO ZERO ===")
showResults(searchForAmount(Q_hf, hf_power, invested));
Log("=== RETURN TWICE ===")
showResults(searchForAmount(Q_hf, hf_power, invested * 2));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment