Last active
May 21, 2017 14:41
-
-
Save gourytch/e5a657303eb0fc52985e0270ba83f555 to your computer and use it in GitHub Desktop.
HashFlare calculator: nodejs version
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* поиск оптимальной стратегии реинвестирования | |
* исходя из параметров майнера и наивной модели | |
* с зафиксированной стоимостью фалюты | |
* с неизменным значением ежедневной прибыльности | |
* и неизменяющейся вычислительной мощностью Сети | |
*/ | |
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