Created
August 8, 2020 02:16
-
-
Save vladgovor77771/55d8019ab307824a239684090a7dfddf to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| const { TmItem, SteamItem, TmMetaAnalysis } = require('../../../models'); | |
| const { Op } = require('sequelize'); | |
| const getBotSettings = require('../get_bot_settings'); | |
| module.exports = run = async (job) => { | |
| let { botId } = job.data; | |
| let { | |
| minPrice, | |
| maxPrice, | |
| buyDiscont, | |
| sellFee, | |
| needProfit, | |
| safeProfit, | |
| timeOffsetMonths, | |
| minCount, | |
| maxCount, | |
| maxLootfarmPriceRate, | |
| // minSteamPriceRate, | |
| minPopularity, | |
| maxConcurrentsByPopularity, | |
| // stick, | |
| // stickPlus | |
| } = await getBotSettings(botId); | |
| let items = await TmItem.findAll({ | |
| limit: 150, | |
| order: [[ TmItem.metaAnalysis, 'profit', 'DESC' ]], | |
| include: [ | |
| { association: TmItem.sellOrders }, | |
| { association: TmItem.buyOrders }, | |
| { | |
| association: TmItem.metaAnalysis, | |
| required: true, | |
| where: { | |
| timeOffsetMonths, | |
| minCount: { [Op.gt]: minCount }, | |
| maxCount: { [Op.gt]: maxCount }, | |
| lootfarmPriceRate: { [Op.lte]: maxLootfarmPriceRate }, | |
| // steamPriceRate: { [Op.gte]: minSteamPriceRate }, | |
| average: { | |
| [Op.and]: { | |
| [Op.gte]: minPrice * buyDiscont, | |
| [Op.lte]: maxPrice * buyDiscont | |
| } | |
| }, | |
| popularity: { [Op.gte]: minPopularity }, | |
| concurrentsByPopularity: { [Op.lte]: maxConcurrentsByPopularity } | |
| }, | |
| } | |
| ] | |
| }) | |
| console.log(items); | |
| // calculate profit | |
| // let profit = parseFloat((sellPrice * sellFee) / (buyPrice * buyDiscount) * 100).toFixed(2)); | |
| // somehow filter due to many bots | |
| } |
This file contains hidden or 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
| const { TmItem, SteamItem, TmMetaAnalysis } = require('../../models'); | |
| const moment = require('moment'); | |
| const _ = require('lodash'); | |
| const CurrencyManager = require('../../helpers/currency_manager'); | |
| module.exports = async (job) => { | |
| let { itemId } = job.data; | |
| await analyse(itemId); | |
| } | |
| const analyse = async (id) => { | |
| let item = await TmItem.findByPk(id, { | |
| include: [{ | |
| association: TmItem.sellings, | |
| required: true, | |
| order: [['date', 'DESC']] | |
| }, { | |
| association: TmItem.sellOrders, | |
| required: true, | |
| }, { | |
| association: TmItem.buyOrders, | |
| required: true, | |
| }, { | |
| association: TmItem.steamItem, | |
| required: true, | |
| include: [{ | |
| association: SteamItem.lootfarmItem, | |
| }] | |
| }, { | |
| association: TmItem.metaAnalysis | |
| }] | |
| }); | |
| let meta2Months = calculateMeta(item); | |
| meta2Months.totalPoints = item.sellings.length; | |
| meta2Months.totalPopulatiry = Math.min(calculatePopularity(item), 100); | |
| if (item.steamItem.lootfarmItem) { | |
| meta2Months.lootfarmPriceRate = (await CurrencyManager.convertToUsd(meta2Months.sellPrice)) / item.steamItem.lootfarmItem.price; | |
| meta2Months.steamPriceRate = meta2Months.lootfarmPriceRate * item.steamItem.lootfarmItem.steamRate; | |
| } else { | |
| meta2Months.steamPriceRate = (await CurrencyManager.convertToUsd(meta2Months.sellPrice)) / item.steamItem.price; | |
| } | |
| let existedAnalysis = item.metaAnalysis.find(anal => anal.timeOffsetMonths == 2); | |
| if (existedAnalysis) await existedAnalysis.update(meta2Months); | |
| else await TmMetaAnalysis.create({ itemId: item.id, ...meta2Months }); | |
| // let meta1Months = calculateMeta(item, moment().subtract(1, 'months').toDate()); | |
| // let meta3Months = calculateMeta(item, moment().subtract(3, 'months').toDate()); | |
| } | |
| const calculateMeta = (item, timeFrom = moment().subtract(2, 'months').toDate()) => { | |
| let overPriceDetect = 0.91; // отходим ко второму ордеру если первый дороже на 9%, постоянная? | |
| let sellings = item.sellings.filter(selling => selling.date > timeFrom); | |
| let sellingsCount = sellings.length; | |
| let popularity = Math.min(calculatePopularity(sellings), 100); | |
| let mounthAgo = Math.min(Math.round((popularity / 100) * (50 - 15) + 15), item.sellings.length); | |
| let minest = Math.min.apply(null, item.sellings.slice(0, mounthAgo).map(item => item.price)); | |
| let { buyPrice, sellPrice, maxCount, minCount, average } = calculateBuySellPrice({ sellings: item.sellings, mounthAgo }); | |
| if (item.sellOrders.count > 0 && item.sellOrders.length >= 2 && item.sellOrders.bestOrder / item.sellOrders.value[1][0] < overPriceDetect) { | |
| if (sellPrice > item.sellOrders.value[1][0]) sellPrice = item.sellOrders.value[1][0]; | |
| else if (sellPrice > item.sellOrders.bestOrder) sellPrice = item.sellOrders.bestOrder; | |
| } | |
| let sellConcurrents = 0; | |
| item.sellOrders.value.map(e => { if (e[0] < sellPrice) sellConcurrents += e[1] }); | |
| if (item.buyOrders.length >= 2 && item.buyOrders.bestOrder / item.buyOrders.value[1][0] < overPriceDetect) { | |
| if (buyPrice < item.buyOrders.value[1][0]) buyPrice = item.buyOrders.value[1][0]; | |
| else buyPrice = Math.max(buyPrice, item.buyOrders.bestOrder, minest); | |
| } | |
| let res = { | |
| sellingsCount, | |
| popularity, | |
| buyPrice, | |
| sellPrice, | |
| sellConcurrents, | |
| concurrentsByPopularity: sellConcurrents / popularity, | |
| maxCount, | |
| minCount, | |
| average, | |
| profit: sellPrice / buyPrice, | |
| } | |
| return res; | |
| } | |
| const calculatePopularity = (sellings) => { | |
| return sellings.length / ((sellings[0].date - sellings[sellings.length - 1].date) / 1000 / 60 / 60 / 24); | |
| } | |
| const calculateAveragePrice = (sellings) => { | |
| if (sellings.length < 1) return 0; | |
| let sorted = _.sortBy(sellings, 'price'); | |
| if (sorted.length % 2 == 1) return sorted[Math.floor(sorted.length / 2)].price; | |
| else return (sorted[Math.floor(sorted.length / 2) - 1].price + sorted[Math.floor(sorted.length / 2)].price) / 2; | |
| } | |
| const calculateBuySellPrice = ({ sellings, mounthAgo }) => { | |
| let trendWeight = 0.05; // диапазон средних точек 0.08 | |
| let average = calculateAveragePrice(sellings.slice(0, mounthAgo)); | |
| let min = []; | |
| let max = []; | |
| let first = 0; | |
| let last = 0; | |
| let minEl = 0; | |
| let maxEl = 0; | |
| for(var j = 0; j < Math.floor(mounthAgo / 2); j++) { | |
| if (sellings[j].price / average > 2 || sellings[j].price / average < 0.5) continue; | |
| first += sellings[j].price; | |
| if(sellings[j].price < sellings[minEl].price) minEl = j; | |
| if(sellings[j].price > sellings[maxEl].price) maxEl = j; | |
| } | |
| first /= Math.floor(mounthAgo / 2); | |
| for(var j = Math.floor(mounthAgo / 2); j < mounthAgo; j++) { | |
| if (sellings[j].price / average > 2 || sellings[j].price / average < 0.5) continue; | |
| last += sellings[j].price; | |
| if(sellings[j].price < sellings[minEl].price) minEl = j; | |
| if(sellings[j].price > sellings[maxEl].price) maxEl = j; | |
| } | |
| last /= mounthAgo - Math.floor(mounthAgo / 2); | |
| let step = (last - first) / (mounthAgo - 1); | |
| let range = sellings[maxEl].price - sellings[minEl].price; | |
| for(var j = 0; j < mounthAgo; j++) { | |
| let diff = sellings[j].price; | |
| if (diff / average > 2 || diff / average < 0.5) continue; | |
| let trend = first + j * step; | |
| let normtrend = trend / range; | |
| let normdiff = diff / range / normtrend; | |
| if(normdiff < 1 + trendWeight && normdiff > 1 - trendWeight) continue; | |
| if(normdiff > 1) max.push(sellings[j]); | |
| else min.push(sellings[j]); | |
| } | |
| let buyPrice = calculateAveragePrice(min); | |
| let sellPrice = calculateAveragePrice(max); | |
| let maxCount = max.length; | |
| let minCount = min.count; | |
| return { buyPrice, sellPrice, maxCount, minCount, average } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment