internal protected AerialCombatStage(BattleInfo rpOwner, ApiData rpData) : base(rpOwner) { var rRawData = rpData.Data as IAerialCombatSecondRound; AerialCombatFirstRound = new AerialCombatPhase(this, rRawData.AerialCombat, PhaseRound.First); AerialCombatSecondRound = new AerialCombatPhase(this, rRawData.AerialCombatSecondRound, PhaseRound.Second); }
void ProcessAbyssalFleet(ApiData rpData) { var rData = rpData.Data as RawBattleBase; var rFormation = rpData.Data as IRawFormationAndEngagementForm; if (rData == null || rFormation == null) return; var rEnemies = rData.EnemyShipTypeIDs.Where(r => r != -1).ToArray(); var rBytes = new byte[rEnemies.Length * sizeof(int)]; Buffer.BlockCopy(rEnemies, 0, rBytes, 0, rBytes.Length); long rCompositionID; using (var rSHA1 = SHA1.Create()) { var rHash = rSHA1.ComputeHash(rBytes); rCompositionID = BitConverter.ToInt64(rHash, 0); } int rNodeID; var rSortie = SortieInfo.Current; if (rSortie.Node.WikiID.IsNullOrEmpty()) rNodeID = rSortie.Node.ID << 16; else rNodeID = rSortie.Node.WikiID[0] - 'A'; using (var rTransaction = r_Connection.BeginTransaction()) { using (var rCommand = r_Connection.CreateCommand()) { var rBuilder = new StringBuilder(256); rBuilder.Append("INSERT OR IGNORE INTO composition(id, position, ship) VALUES"); for (var i = 0; i < rEnemies.Length; i++) { rBuilder.Append($"({rCompositionID}, {i}, {rEnemies[i]})"); if (i < rEnemies.Length - 1) rBuilder.Append(','); } rBuilder.Append(';'); rBuilder.Append("INSERT OR IGNORE INTO fleet(map, node, difficulty, formation, composition, synced) VALUES(@map, @node, @difficulty, @formation, @composition, 0);"); rCommand.CommandText = rBuilder.ToString(); rCommand.Parameters.AddWithValue("@map", rSortie.Map.ID); rCommand.Parameters.AddWithValue("@node", rNodeID); rCommand.Parameters.AddWithValue("@difficulty", (int?)rSortie.Map.Difficulty ?? 0); rCommand.Parameters.AddWithValue("@formation", rFormation.FormationAndEngagementForm[1]); rCommand.Parameters.AddWithValue("@composition", rCompositionID); rCommand.ExecuteNonQuery(); } rTransaction.Commit(); } }
internal protected DayNormalStage(BattleInfo rpOwner, ApiData rpData) : base(rpOwner) { var rRawData = rpData.Data as RawDay; AerialCombat = new AerialCombatPhase(this, rRawData.AerialCombat); SupportingFire = new SupportingFirePhase(this, rRawData.SupportingFire); OpeningTorpedo = new TorpedoSalvoPhase(this, rRawData.OpeningTorpedoSalvo); ShellingFirstRound = new ShellingPhase(this, rRawData.ShellingFirstRound); ShellingSecondRound = new ShellingPhase(this, rRawData.ShellingSecondRound); ClosingTorpedo = new TorpedoSalvoPhase(this, rRawData.ClosingTorpedoSalvo); }
static void ApiResponse(HttpListenerResponse response, HttpListenerRequest request) { response.StatusCode = 200; response.ContentType = "application/json"; ApiData r = new ApiData(); r.Status = 200; r.Value = "foo"; var serializer = new DataContractJsonSerializer(typeof(ApiData)); serializer.WriteObject(response.OutputStream, r); }
internal Impl(ApiData shippedData, ApiData unshippedData) { _unshippedData = unshippedData; foreach (ApiLine cur in shippedData.ApiList) { _publicApiMap.Add(cur.Text, cur); } foreach (ApiLine cur in unshippedData.ApiList) { _publicApiMap.Add(cur.Text, cur); } }
internal Impl(ApiData shippedData, ApiData unshippedData) { this.unshippedData = unshippedData; foreach (var cur in shippedData.ApiList) { this.publicApiMap.Add(cur.Text, cur); } foreach (var cur in unshippedData.ApiList) { this.publicApiMap.Add(cur.Text, cur); } }
internal protected CombinedFleetCTFDayNormalStage(BattleInfo rpOwner, ApiData rpData) : base(rpOwner) { var rRawData = rpData.Data as RawCombinedFleetDay; LandBaseAerialSupport = new LandBaseAerialSupportPhase(this, rRawData.LandBaseAerialSupport); AerialCombat = new AerialCombatPhase(this, rRawData.AerialCombat); SupportingFire = new SupportingFirePhase(this, rRawData.SupportingFire); OpeningTorpedo = new TorpedoSalvoPhase(this, rRawData.OpeningTorpedoSalvo, true); ShellingFirstRound = new ShellingPhase(this, rRawData.ShellingFirstRound, true); ClosingTorpedo = new TorpedoSalvoPhase(this, rRawData.ClosingTorpedoSalvo, true); ShellingSecondRound = new ShellingPhase(this, rRawData.ShellingSecondRound); ShellingThirdRound = new ShellingPhase(this, rRawData.ShellingThirdRound); }
internal void Process(ApiData rpData) { var rData = rpData.Data as RawBattleBase; FriendAndEnemy = rData.CurrentHPs.Zip(rData.MaximumHPs, (rpCurrent, rpMaximum) => rpMaximum != -1 ? new BattleParticipantSnapshot(rpMaximum, rpCurrent) : null).Skip(1).ToArray(); FriendMain = FriendAndEnemy.Take(6).TakeWhile(r => r != null).ToList().AsReadOnly(); for (var i = 0; i < FriendMain.Count; i++) FriendMain[i].Participant = Owner.Participants.FriendMain[i]; Enemy = FriendAndEnemy.Skip(6).TakeWhile(r => r != null).ToList().AsReadOnly(); for (var i = 0; i < Enemy.Count; i++) Enemy[i].Participant = Owner.Participants.Enemy[i]; var rCombinedFleetData = rData as IRawCombinedFleet; if (rCombinedFleetData != null) { FriendEscort = rCombinedFleetData.EscortFleetCurrentHPs.Zip(rCombinedFleetData.EscortFleetMaximumHPs, (rpCurrent, rpMaximum) => rpMaximum != -1 ? new BattleParticipantSnapshot(rpMaximum, rpCurrent) : null).Skip(1).ToList().AsReadOnly(); for (var i = 0; i < FriendMain.Count; i++) FriendEscort[i].Participant = Owner.Participants.FriendEscort[i]; FriendAndEnemy = Enumerable.Concat(FriendAndEnemy, FriendEscort).ToArray(); } if (FriendEscort == null) Friend = FriendMain; else Friend = FriendMain.Concat(FriendEscort).ToList().AsReadOnly(); foreach (var rPhase in Phases) rPhase.Process(); if (!Owner.IsPractice) foreach (var rSnapshot in Friend) { var rParticipant = (FriendShip)rSnapshot.Participant; if (rSnapshot.State == BattleParticipantState.HeavilyDamaged && rParticipant.EquipedEquipment.Any(r => r.Info.Type == EquipmentType.DamageControl)) { rParticipant.IsDamageControlConsumed = false; rParticipant.IsDamageControlVisible = true; } } }
internal void Process(ApiData rpData) { var rData = rpData.Data as RawBattleBase; FriendAndEnemy = rData.CurrentHPs.Zip(rData.MaximumHPs, (rpCurrent, rpMaximum) => rpMaximum != -1 ? new BattleParticipantSnapshot(rpMaximum, rpCurrent) : null).Skip(1).ToArray(); FriendMain = FriendAndEnemy.Take(6).TakeWhile(r => r != null).ToList().AsReadOnly(); for (var i = 0; i < FriendMain.Count; i++) FriendMain[i].Participant = Owner.Participants.FriendMain[i]; Enemy = FriendAndEnemy.Skip(6).TakeWhile(r => r != null).ToList().AsReadOnly(); for (var i = 0; i < Enemy.Count; i++) Enemy[i].Participant = Owner.Participants.Enemy[i]; var rCombinedFleetData = rData as IRawCombinedFleet; if (rCombinedFleetData != null) { FriendEscort = rCombinedFleetData.EscortFleetCurrentHPs.Zip(rCombinedFleetData.EscortFleetMaximumHPs, (rpCurrent, rpMaximum) => rpMaximum != -1 ? new BattleParticipantSnapshot(rpMaximum, rpCurrent) : null).Skip(1).ToList().AsReadOnly(); for (var i = 0; i < FriendMain.Count; i++) FriendEscort[i].Participant = Owner.Participants.FriendEscort[i]; FriendAndEnemy = Enumerable.Concat(FriendAndEnemy, FriendEscort).ToArray(); } foreach (var rPhase in Phases) rPhase.Process(); var rMaxDamage = FriendMain.Max(r => r.DamageGivenToOpponent); ((FriendShip)FriendMain.First(r => r.DamageGivenToOpponent == rMaxDamage).Participant).IsMVP = true; if (FriendEscort != null) { rMaxDamage = FriendEscort.Max(r => r.DamageGivenToOpponent); ((FriendShip)FriendEscort.First(r => r.DamageGivenToOpponent == rMaxDamage).Participant).IsMVP = true; } }
void ProcessFirstStage(ApiData rpData) { SetEnemy((RawBattleBase)rpData.Data); SetFormationAndEngagementForm(rpData); switch (rpData.Api) { case "api_req_sortie/battle": case "api_req_practice/battle": First = new DayNormalStage(this, rpData); break; case "api_req_battle_midnight/sp_midnight": First = new NightOnlyStage(this, rpData); break; case "api_req_sortie/airbattle": case "api_req_combined_battle/airbattle": First = new AerialCombatStage(this, rpData); break; case "api_req_combined_battle/battle": First = new CombinedFleetCTFDayNormalStage(this, rpData); break; case "api_req_combined_battle/battle_water": First = new CombinedFleetSTFDayNormalStage(this, rpData); break; case "api_req_combined_battle/sp_midnight": First = new CombinedFleetNightOnlyStage(this, rpData); break; } First.Process(rpData); Result.Update(First, Second); IsInitialized = true; CurrentStage = First; OnPropertyChanged(nameof(First)); OnPropertyChanged(nameof(CurrentStage)); OnPropertyChanged(nameof(AerialCombat)); OnPropertyChanged(nameof(IsInitialized)); }
private static bool TryGetApiData(ImmutableArray <AdditionalText> additionalTexts, CancellationToken cancellationToken, out ApiData shippedData, out ApiData unshippedData) { if (!TryGetApiText(additionalTexts, cancellationToken, out var shippedText, out var unshippedText)) { shippedData = default; unshippedData = default; return(false); } shippedData = ReadApiData(shippedText.Path, shippedText.GetText(cancellationToken), isShippedApi: true); unshippedData = ReadApiData(unshippedText.Path, unshippedText.GetText(cancellationToken), isShippedApi: false); return(true); }
private async Task MinuteCandleByTicksAsync() { // 설정값 var coinName = Coin.Ticker; var candleType = CandleType.Name; var candleMinute = CandleType.Minute; var candleCount = CandleCount; var feeRate = FeeRate; var tradeRate = OrderRate; var triggerRate = TriggerRate; // 캔들 갯수 많큼 캔들 가져오기 var candles = ApiData.getCandle <List <Candle> >(coinName, candleType, candleCount * 2); // 캔들 조회 (2배로 여유롭게) var currPrice = candles.First().Close; // 현재가 var prevPrice = candles[1].Low; // 직전저가 var highPrice = candles.GetRange(1, candleCount - 1).Max(x => x.High); // 최고가 var downPrice = highPrice * (triggerRate + (feeRate * (candleCount - 1))) / 100; // 하락가 var triggerDownPrice = highPrice - downPrice; // 매수 하락 촉발가 var downRate = Math.Min(0D, (currPrice - highPrice) * 100 / highPrice); // 하락율 var upPrice = prevPrice * (feeRate * (candleCount - 1)) / 100; // 반등가 var triggerUpPrice = prevPrice + upPrice; // 매수 반등 촉발가 var upRate = (currPrice - prevPrice) * 100 / prevPrice; // 반등 상승율 var downUpRate = upRate <= 0 && downRate <= 0 ? 0D : (-downRate / upRate); // 반등율 // 보유현금 및 주문 정보 var orderChance = ApiData.getOrdersChance(coinName); // 주문 가능 정보 var bid = orderChance["bid_account"]; var ask = orderChance["ask_account"]; var krwBalance = bid.Value <double>("balance"); // 보유 현금 var coinVol = ask.Value <double?>("balance") ?? 0D; // 보유 코인 수량 var avgPrice = ask.Value <double?>("avg_buy_price") ?? 0D; // 매수 평단가 var buyLock = bid.Value <double?>("locked") ?? 0D; // 매수 대기 금액 var sellLock = ask.Value <double?>("locked") ?? 0D; // 매도 대기 금액 var coinBuyBalance = avgPrice * coinVol; // 코인 매수금 var coinBalance = currPrice * coinVol; // 코인 평가금 var totalBalance = krwBalance + coinBalance; // 현재 자산 var minTradeKRW = Settings.Default.minTradeKRW; // 최소 거래 금액 var fee = currPrice * feeRate / 100; // 거래 수수료 var sellFee = coinBalance * feeRate / 100; // 매도 총 수수료 var buyFee = totalBalance * feeRate / 100; // 매수 총 수수료 var buyUnitPrice = GetOrderUnitPrice(krwBalance); // 매수 주문 가격 단위 var sellUnitPrice = GetOrderUnitPrice(coinBalance); // 매도 주문 가격 단위 // 거래 쿨다운 타임 var buyTs = (DateTime.Now - LastSellDate).TotalSeconds; // 마지막 매도 이후 경과 시간 (초) var buyCoolDownSec = CandleType.Minute * 60 * (candleCount - 2) / (candleCount - 1); // 매수 쿨다운 시간 (초) var buyRemainCoolDownSec = buyCoolDownSec - buyTs; // 매수 쿨다운 시간 (초) var sellTs = (DateTime.Now - LastBuyDate).TotalSeconds; // 마지막 매수 이후 경과 시간 (초) var sellCoolDownSec = (CandleType.Minute + (1 / candleCount)) * 60; // 매도 쿨다운 시간 (초) var sellRemainCoolDownSec = sellCoolDownSec - sellTs; // 매도 까지 남은 시간 (초) var targetRate = ((triggerRate / 2) + (feeRate * 2)) / 100; // 목표 수익율 var targetSellPrice = Math.Round(avgPrice * (1 + targetRate) / 10) * 10; // 매도 목표가 var now = DateTime.Now; var line1 = $"[{now:T}] {coinName}"; line1 += $" : 현재/직전/최고 {currPrice:N0}/{prevPrice:N0}/{highPrice:N0}"; line1 += $", 하락율/반등율 {downRate:F2}/{upRate:F2}, 평단가 {avgPrice:N0}"; line1 += (sellRemainCoolDownSec > 0) ? $", 매수쿨 {sellRemainCoolDownSec:N0}(초)" : ""; line1 += (buyRemainCoolDownSec > 0) ? $", 매도쿨 {buyRemainCoolDownSec:N0}(초)" : ""; var line2 = $"[{now:T}] {coinName}"; line2 += $" : 시작자산 {StartKRW:N0}, 현재자산 {totalBalance:N0}"; line2 += $", 매수촉발가(하락/반등) {triggerDownPrice:N0} / {triggerUpPrice:N0}, 매도 목표가 {targetSellPrice:N0}, 매수 수수료 {totalBalance * feeRate / 100:F2}"; WriteCurrent("{0}\r\n{1}", line1, line2); if (StartKRW < minTradeKRW && krwBalance > minTradeKRW && coinBalance < minTradeKRW) { // 거래 시작 금액 StartKRW = krwBalance; } if (InvokeRequired) { BeginInvoke(new Action(() => { txtKRWBalance.Text = krwBalance.ToString("N0"); txtCoinBalance.Text = coinBalance.ToString("N0"); txtBalance.Text = totalBalance.ToString("N0"); txtStartKRW.Text = StartKRW.ToString("N0"); })); } else { txtKRWBalance.Text = krwBalance.ToString("N0"); txtCoinBalance.Text = coinBalance.ToString("N0"); txtBalance.Text = totalBalance.ToString("N0"); txtStartKRW.Text = StartKRW.ToString("N0"); } try { var orderResult = null as JObject; var order = null as JObject; var uuid = ""; var side = ""; var state = ""; if (IsWaiting) { // 거래 대기 중일때 uuid = LastOrderResult.Value <string>("uuid"); side = LastOrderResult.Value <string>("side"); state = LastOrderResult.Value <string>("state"); WriteLog("#### 거래 불가(거래 대기중) : side {0}, state {1}, uuid {2}", side, state, uuid); return; } if (coinBalance <= minTradeKRW && krwBalance <= minTradeKRW) { // 보유현금과 보유 코인이 최소 거래금액 보다 적으면 거래 없음 WriteLog("#### 거래 불가(금액 부족) : 보유현금 {0}, 코인보유금 {1}, 매도 대기 금액 {2}, 매수 대기 금액 {3}, 최소 거래 금액 {4}", krwBalance, coinBalance, buyLock, sellLock, minTradeKRW); return; } if (krwBalance > minTradeKRW && // 보유 현금이 최소거래 금액 보다 클때 buyRemainCoolDownSec <= 0 && // 매도 유예시간이 지났을때 currPrice <= Math.Truncate(triggerDownPrice) && currPrice >= Math.Truncate(triggerUpPrice) && // 현재가가 촉발 금액 사이에서 반등하고 downUpRate <= candleCount * 2) // 반등율이 캔들갯수의 2배수가 넘지 않아야 함 { // BUY var unitPrice = GetOrderUnitPrice(currPrice); var total = Math.Truncate(coinBalance / unitPrice) * unitPrice; var avgBuyPrice = currPrice; orderResult = React.executeDeal(true, false, coinName, 0, 0, total); IsWaiting = true; LastBuyDate = DateTime.Now; WriteLog("#### BUY : {0}", orderResult.ToString(Formatting.Indented)); var buyUUID = orderResult.Value <string>("uuid"); var buyOrderResult = await GetBuyResultAsync(buyUUID); // SELL if (buyOrderResult != null) { var buyPrice = buyOrderResult.Value <double>("price"); var targetBuyPrice = GetOrderUnitPrice(buyPrice + Math.Max((buyPrice * 0.5 / 100) + (fee * 2), 10)); var buyVol = buyOrderResult.Value <double>("executed_volume"); var sellResult = await GetSellResultAsync(coinName, targetBuyPrice, buyVol); IsWaiting = false; LastBuyDate = DateTime.Now; WriteLog("#### SELL : {0}", sellResult.ToString(Formatting.Indented)); if (sellResult != null) { var sellUuid = sellResult.Value <string>("uuid"); var sellState = sellResult.Value <string>("state"); var sellPrice = sellResult.Value <double?>("price") ?? 0D; var sellVolume = sellResult.Value <double?>("volume") ?? 0D; var tradeCount = sellResult.Value <double>("trade_count"); var trades = order["trades"] as JArray; var tradePrice = 0D; var tradeVolume = 0D; var tradeFunds = 0D; if (trades != null && trades.Count > 0) { tradePrice = trades[0].Value <double?>("price") ?? 0D; tradeVolume = trades[0].Value <double?>("volume") ?? 0D; tradeFunds = trades[0].Value <double?>("funds") ?? 0D; } // SELL WriteLog("#### {0} SELL : 금액 {1:N0} : 평단가 {2:N0} : 수량 {3:F6}", coinName, tradeFunds, tradePrice, tradeVolume); // 수익 var balance = GetBalance(coinName); krwBalance = balance.KRWBalance; coinBalance = currPrice * balance.CoinVol; totalBalance = krwBalance + coinBalance; var profit = totalBalance - StartKRW; var profitRate = (StartKRW == 0) ? 0D : profit / StartKRW * 100; if (InvokeRequired) { BeginInvoke(new Action(() => { txtKRWBalance.Text = krwBalance.ToString("N0"); txtCoinBalance.Text = coinBalance.ToString("N0"); txtBalance.Text = totalBalance.ToString("N0"); txtProfitPrice.Text = profit.ToString("N0"); txtProfitRate.Text = profitRate.ToString("F4"); })); } else { txtKRWBalance.Text = krwBalance.ToString("N0"); txtCoinBalance.Text = coinBalance.ToString("N0"); txtBalance.Text = totalBalance.ToString("N0"); txtProfitPrice.Text = profit.ToString("N0"); txtProfitRate.Text = profitRate.ToString("F4"); } var args = new object[] { coinName, StartKRW, totalBalance, profit, profitRate, krwBalance, coinBalance }; WriteLog("#### {0} 수익 : 거래시작금액 {1:N0}, 현재평가 금액 {2:N0}, 수익금액 {3:N0}, 수익율 {4:F6}, 보유현금 {5:N0}, 코인 평가 {6:N0}", args); } } } } catch (Exception ex) { WriteLog(ex.StackTrace); } }
public async Task PostCountryBbsAsync( [FromBody] ThreadBbsItem param) { ThreadBbsItem message; Character chara; using (var repo = MainRepository.WithReadAndWrite()) { chara = await repo.Character.GetByIdAsync(this.AuthData.CharacterId).GetOrErrorAsync(ErrorCode.LoginCharacterNotFoundError); if (await repo.BlockAction.IsBlockedAsync(chara.Id, BlockActionType.StopBbs)) { ErrorCode.BlockedActionError.Throw(); } var iconId = param.CharacterIconId; if (iconId == 0) { iconId = (await repo.Character.GetCharacterAllIconsAsync(chara.Id)).GetMainOrFirst().Data?.Id ?? 0; } if (param.ParentId != 0) { var parent = await repo.ThreadBbs.GetByIdAsync(param.ParentId).GetOrErrorAsync(ErrorCode.ParentNodeNotFoundError); if (parent.CountryId != chara.CountryId) { ErrorCode.NotPermissionError.Throw(); } if (parent.ParentId != 0) { ErrorCode.NotTopNodeError.Throw(); } if (!string.IsNullOrEmpty(param.Title)) { ErrorCode.LackOfParameterError.Throw(); } } else { if (string.IsNullOrEmpty(param.Title)) { ErrorCode.InvalidParameterError.Throw(); } } message = new ThreadBbsItem { CharacterId = chara.Id, CountryId = chara.CountryId, ParentId = param.ParentId, Title = param.Title, Text = param.Text, CharacterIconId = iconId, Written = DateTime.Now, Type = BbsType.CountryBbs, }; await repo.ThreadBbs.AddAsync(message); await repo.SaveChangesAsync(); var icon = await repo.Character.GetCharacterIconByIdAsync(iconId); message.Character = new CharacterForAnonymous(chara, icon, CharacterShareLevel.Anonymous); } await StatusStreaming.Default.SendCountryAsync(ApiData.From(message), chara.CountryId); }
public ManagerForm(LogCache logCache, ApiData apiData) { LogCache = logCache ?? throw new ArgumentNullException(nameof(logCache)); ApiData = apiData ?? throw new ArgumentNullException(nameof(apiData)); // Background processors var dpsReportUploader = new DpsReportUploader(); UploadProcessor = new UploadProcessor(dpsReportUploader, LogCache); ApiProcessor = new ApiProcessor(ApiData, new Gw2Client()); LogDataProcessor = new LogDataProcessor(LogCache, ApiProcessor, LogAnalytics); LogNameProvider = new TranslatedLogNameProvider(GameLanguage.English); LogDataProcessor.StoppingWithError += (sender, args) => { Application.Instance.InvokeAsync(() => MessageBox.Show(this, $"The background processor for logs has failed critically. " + $"Please report the following error:\n\nException: {args.Exception}", "Error", MessageBoxType.Error)); }; ApiProcessor.StoppingWithError += (sender, args) => { Application.Instance.InvokeAsync(() => MessageBox.Show(this, $"The background processor for API requests has failed critically. " + $"Please report the following error:\n\nException: {args.Exception}", "Error", MessageBoxType.Error)); }; UploadProcessor.StoppingWithError += (sender, args) => { Application.Instance.InvokeAsync(() => MessageBox.Show(this, $"The background processor for log uploads has failed critically. " + $"Please report the following error:\n\nException: {args.Exception}", "Error", MessageBoxType.Error)); }; Filters = new LogFilters(new SettingsFilters()); Filters.PropertyChanged += (sender, args) => logsFiltered.Refresh(); if (Settings.UseGW2Api) { ApiProcessor.StartBackgroundTask(); } Settings.UseGW2ApiChanged += (sender, args) => { if (Settings.UseGW2Api) { ApiProcessor.StartBackgroundTask(); } else { ApiProcessor.StopBackgroundTask(); } }; Settings.DpsReportDomainChanged += (sender, args) => { dpsReportUploader.Domain = Settings.DpsReportDomain; }; // Form layout Icon = Resources.GetProgramIcon(); Title = "arcdps Log Manager"; ClientSize = new Size(1300, 768); var formLayout = new DynamicLayout(); Content = formLayout; Menu = ConstructMenuBar(); formLayout.BeginVertical(new Padding(5), yscale: false); { formLayout.Add(ConstructMainSplitter(), yscale: true); formLayout.Add(ConstructStatusPanel()); } formLayout.EndVertical(); // Event handlers ApiProcessor.Processed += (sender, args) => { bool last = args.CurrentScheduledItems == 0; if (last) { ApiData.SaveDataToFile(); } }; Settings.LogRootPathChanged += (sender, args) => Application.Instance.Invoke(ReloadLogs); Closing += (sender, args) => { if (LogCache?.ChangedSinceLastSave ?? false) { LogCache?.SaveToFile(); } ApiData?.SaveDataToFile(); }; LogSearchFinished += (sender, args) => { var updates = LogDataUpdater.GetUpdates(logs).ToList(); if (updates.Count > 0) { new ProcessingUpdateDialog(LogDataProcessor, updates).ShowModal(this); } }; // Collection initialization logsFiltered = new FilterCollection <LogData>(logs); logsFiltered.CollectionChanged += (sender, args) => FilteredLogsUpdated?.Invoke(this, EventArgs.Empty); logsFiltered.Filter = Filters.FilterLog; LogCollectionsInitialized?.Invoke(this, EventArgs.Empty); LogDataProcessor.Processed += (sender, args) => { bool last = args.CurrentScheduledItems == 0; if (last) { Application.Instance.AsyncInvoke(logsFiltered.Refresh); } }; Shown += (sender, args) => ReloadLogs(); Shown += (sender, args) => CheckUpdates(); }
void ProcessSortieFirstStage(ApiData rpData) { var rSortie = SortieInfo.Current; r_CurrentBattleID = BattleInfo.Current.ID; using (var rTransaction = Connection.BeginTransaction()) using (var rCommand = Connection.CreateCommand()) { var rCommandTextBuilder = new StringBuilder(1024); rCommandTextBuilder.Append("INSERT INTO battle_detail.battle(id, first) VALUES(@battle_id, @first);"); rCommand.Parameters.AddWithValue("@battle_id", r_CurrentBattleID.Value); rCommand.Parameters.AddWithValue("@first", CompressJson(rpData.Json["api_data"])); ProcessParticipantFleet(rCommandTextBuilder, rSortie.Fleet, ParticipantFleetType.Main); if (rSortie.EscortFleet != null) ProcessParticipantFleet(rCommandTextBuilder, rSortie.EscortFleet, ParticipantFleetType.Escort); var rData = rpData.Data as RawDay; if (rData != null && rData.SupportingFireType != 0) { var rSupportFire = rData.SupportingFire; var rFleetID = (rSupportFire.SupportShelling?.FleetID ?? rSupportFire.AerialSupport?.FleetID).Value; ProcessParticipantFleet(rCommandTextBuilder, KanColleGame.Current.Port.Fleets[rFleetID], ParticipantFleetType.SupportFire); } rCommand.CommandText = rCommandTextBuilder.ToString(); rCommand.ExecuteNonQuery(); rTransaction.Commit(); } }
internal protected NightOnlyStage(BattleInfo rpOwner, ApiData rpData) : base(rpOwner) { var rRawData = rpData.Data as RawNightOnly; Shelling = new ShellingPhase(this, rRawData.Shelling); }
private void MinuteCandleByTicks() { // 설정값 var coinName = Coin.Ticker; var candleType = CandleType.Name; var candleCount = CandleCount; var feeRate = FeeRate; var tradeRate = OrderRate; var triggerRate = TriggerRate; // 캔들 갯수 많큼 캔들 가져오기 var candles = ApiData.getCandle <List <Candle> >(coinName, candleType, candleCount * 2); // 캔들 조회 (2배로 여유롭게) var currPrice = candles.First().Close; // 현재가 var prevPrice = candles[1].Close; // 직전종가 var highPrice = candles.GetRange(1, candleCount - 1).Max(x => x.High); // 최고가 var downPrice = highPrice * (triggerRate + (feeRate * 2)) / 100; // 하락가 var triggerDownPrice = highPrice - downPrice; // 매수 하락 촉발가 var downRate = Math.Min(0D, (currPrice - highPrice) * 100 / highPrice); // 하락율 var upPrice = prevPrice * ((triggerRate / candleCount) + (feeRate * 2)) / 100; // 반등가 var triggerUpPrice = prevPrice + upPrice; // 매수 반등 촉발가 var upRate = Math.Max(0D, (currPrice - prevPrice) * 100 / prevPrice); // 반등 상승율 var downUpRate = upRate == 0 ? 0D : (-downRate / upRate); // 반등율 // 보유현금 및 주문 정보 var orderChance = ApiData.getOrdersChance(coinName); // 주문 가능 정보 var bid = orderChance["bid_account"]; var ask = orderChance["ask_account"]; var krwBalance = bid.Value <double>("balance"); // 보유 현금 var coinVol = ask.Value <double?>("balance") ?? 0D; // 보유 코인 수량 var avgPrice = ask.Value <double?>("avg_buy_price") ?? 0D; // 매수 평단가 var buyLock = bid.Value <double?>("locked") ?? 0D; // 매수 대기 금액 var sellLock = ask.Value <double?>("locked") ?? 0D; // 매도 대기 금액 var coinBuyBalance = avgPrice * coinVol; // 코인 매수금 var coinBalance = currPrice * coinVol; // 코인 평가금 var totalBalance = krwBalance + coinBalance; // 현재 자산 var minTradeKRW = Settings.Default.minTradeKRW; // 최소 거래 금액 avgPrice = avgPrice == 0D ? currPrice : avgPrice; // 거래 쿨다운 타임 var buyTs = (DateTime.Now - LastSellDate).TotalSeconds; // 마지막 매도 이후 경과 시간 (초) var buyCoolDownSec = CandleType.Minute * 60; // 매수 쿨다운 시간 (초) var buyCountDownSec = buyCoolDownSec - buyTs; // 매수 쿨다운 시간 (초) var sellTs = (DateTime.Now - LastBuyDate).TotalSeconds; // 마지막 매수 이후 경과 시간 (초) var sellCoolDownSec = (CandleType.Minute + (1 / candleCount)) * 60; // 매도 쿨다운 시간 (초) var sellCountDownSec = sellCoolDownSec - sellTs; // 매도 까지 남은 시간 (초) var targetRate = ((triggerRate / (candleCount - 1)) + (feeRate * 2)) / 100; // 목표 수익율 var targetSellPrice = avgPrice + (avgPrice * targetRate); // 매도 목표가 var now = DateTime.Now; var line1 = $"[{now:T}] {coinName}"; line1 += $" : 현재가 {currPrice:N0}, 직전가 {prevPrice:N0}, 최고가 {highPrice:N0}"; line1 += $", 하락율 {downRate:F4}, 반등율 {upRate:F4}, 평단가 {avgPrice:N0}"; line1 += (sellCountDownSec > 0) ? $", 매수 까지 {sellCountDownSec:N0}(초)" : ""; line1 += (buyCountDownSec > 0) ? $", 매도 까지 {buyCountDownSec:N0}(초)" : ""; var line2 = $"[{now:T}] {coinName}"; line2 += $" : 시작자산 {StartKRW:N0}, 현재자산 {totalBalance:N0}"; line2 += $", 매수 하락 촉발가 {triggerDownPrice:N0}, 매수 반등 촉발가 {triggerUpPrice:N0}, 매도 목표가 {targetSellPrice:N0}"; WriteCurrent("{0}\r\n{1}", line1, line2); //WriteLog("orderChance {0}", orderChance.ToString(Formatting.Indented)); if (StartKRW < minTradeKRW && krwBalance > minTradeKRW && coinBalance < minTradeKRW) { // 거래 시작 금액 StartKRW = krwBalance; } txtKRWBalance.Text = krwBalance.ToString("N0"); txtCoinBalance.Text = coinBalance.ToString("N0"); txtBalance.Text = totalBalance.ToString("N0"); txtStartKRW.Text = StartKRW.ToString("N0"); try { var orderResult = null as JObject; var order = null as JObject; var uuid = ""; var side = ""; var state = ""; if (coinBalance <= minTradeKRW && krwBalance <= minTradeKRW) { // 보유현금과 보유 코인이 최소 거래금액 보다 적으면 거래 없음 WriteLog("#### 거래 불가(금액 부족) : 보유현금 {0}, 코인보유금 {1}, 매도 대기 금액 {2}, 매수 대기 금액 {3}, 최소 거래 금액 {4}", krwBalance, coinBalance, buyLock, sellLock, minTradeKRW); return; } if (sellCountDownSec > 0 && buyCountDownSec > 0) { // 거래 쿨타임 일때 WriteLog("#### 거래 불가(쿨타임) : 매수 까지 남은 시간(초) {0}, 매수 까지 남은 시간(초) {1}, 마지막 매수 {2:T}, 마지막 매도 {3:T}", buyCountDownSec, sellCountDownSec, LastSellDate, LastBuyDate); return; } if (IsWaiting) { // 거래 대기 중일때 uuid = LastOrderResult.Value <string>("uuid"); side = LastOrderResult.Value <string>("side"); state = LastOrderResult.Value <string>("state"); WriteLog("#### 거래 불가(거래 대기중) : side {0}, state {1}, uuid {2}", side, state, uuid); return; } if (krwBalance > minTradeKRW && // 보유 현금이 최소거래 금액 보다 클때 currPrice <= Math.Truncate(triggerDownPrice) && currPrice >= Math.Truncate(triggerUpPrice) && // 현재가가 촉발 금액 사이에서 반등하고 downUpRate <= candleCount * 2) // 반등율이 캔들갯수의 2배수가 넘지 않아야 함 { // BUY var total = ToOrderPrice(krwBalance); var avgBuyPrice = currPrice; orderResult = React.executeDeal(true, false, coinName, 0, 0, total); LastBuyDate = DateTime.Now; WriteLog("#### BUY : {0}", orderResult.ToString(Formatting.Indented)); } else if (coinBalance > minTradeKRW && // 코인 보유금이 최소거래 금액 보다 클때 currPrice >= Math.Truncate(targetSellPrice)) // 현재가가 목표 매수 금액보다 클때 { // SELL var vol = coinVol; vol = Math.Truncate(vol * 100000) / 100000; orderResult = React.executeDeal(false, false, coinName, vol, 0, 0); LastSellDate = DateTime.Now; WriteLog("#### SELL : {0}", orderResult.ToString(Formatting.Indented)); } if (orderResult != null) { IsWaiting = true; LastOrderResult = orderResult; uuid = orderResult.Value <string>("uuid"); side = orderResult.Value <string>("side"); state = orderResult.Value <string>("state"); System.Threading.Thread.Sleep(1500); order = ApiData.checkOrder(uuid); if (order != null) { IsWaiting = false; WriteLog("#### TRADE RESULT : {0}", order.ToString(Formatting.Indented)); var orderState = order.Value <string>("state"); var orderPrice = order.Value <double?>("price") ?? 0D; var orderVolume = order.Value <double?>("volume") ?? 0D; var tradeCount = order.Value <double>("trade_count"); var trades = order["trades"] as JArray; var tradePrice = trades[0].Value <double?>("price") ?? 0D; var tradeVolume = trades[0].Value <double?>("volume") ?? 0D; var tradeFunds = trades[0].Value <double?>("funds") ?? 0D; if ("done".Equals(orderState)) { if ("bid".Equals(side)) { // BUY WriteLog("#### {0} BUY : 매수금 {1:N0} : 매수 평단가 {2:N0} : 수량 {3:F6}", coinName, tradeFunds, tradePrice, tradeVolume); } else if ("ask".Equals(side)) { // SELL WriteLog("#### {0} SELL : 매도금 {1:N0} : 매도 평단가 {2:N0} : 수량 {3:F6}", coinName, tradeFunds, tradePrice, tradeVolume); } // 수익 var balance = GetBalance(coinName); krwBalance = balance.KRWBalance; coinBalance = currPrice * balance.CoinVol; totalBalance = krwBalance + coinBalance; var profit = totalBalance - StartKRW; var profitRate = (StartKRW == 0) ? 0D : profit / StartKRW * 100; txtKRWBalance.Text = krwBalance.ToString("N0"); txtCoinBalance.Text = coinBalance.ToString("N0"); txtBalance.Text = totalBalance.ToString("N0"); txtProfitPrice.Text = profit.ToString("N0"); txtProfitRate.Text = profitRate.ToString("F4"); var args = new object[] { coinName, StartKRW, totalBalance, profit, profitRate, krwBalance, coinBalance }; WriteLog("#### {0} 수익 : 거래시작금액 {1:N0}, 현재평가 금액 {2:N0}, 수익금액 {3:N0}, 수익율 {4:F6}, 보유현금 {5:N0}, 코인 평가 {6:N0}", args); } } else { WriteLog("#### 거래 결과를 가져올수 없습니다."); } } } catch (Exception ex) { WriteLog(ex.StackTrace); } }
void ProcessSecondStage(ApiData rpData) { if (!r_CurrentBattleID.HasValue) return; using (var rCommand = Connection.CreateCommand()) { rCommand.CommandText = "UPDATE battle_detail.battle SET second = @second WHERE id = @id;"; rCommand.Parameters.AddWithValue("@id", r_CurrentBattleID.Value); rCommand.Parameters.AddWithValue("@second", CompressJson(rpData.Json["api_data"])); rCommand.ExecuteNonQuery(); } }
void ProcessResult(ApiData rpData) { if (!r_CurrentBattleID.HasValue) return; using (var rTransaction = Connection.BeginTransaction()) { using (var rCommand = Connection.CreateCommand()) { rCommand.CommandText = "UPDATE battle_detail.battle SET result = @result WHERE id = @id;"; rCommand.Parameters.AddWithValue("@id", r_CurrentBattleID.Value); rCommand.Parameters.AddWithValue("@result", CompressJson(rpData.Json["api_data"])); if (rpData.Api == "api_req_practice/battle_result") { rCommand.CommandText += "UPDATE battle_detail.practice SET rank = @rank WHERE id = @id;"; rCommand.Parameters.AddWithValue("@rank", (int)((RawBattleResult)rpData.Data).Rank); } rCommand.ExecuteNonQuery(); } var rStage = BattleInfo.Current.CurrentStage; ProcessHeavilyDamagedShip(rStage.FriendMain, ParticipantFleetType.Main); if (rStage.FriendEscort != null) ProcessHeavilyDamagedShip(rStage.FriendEscort, ParticipantFleetType.Escort); rTransaction.Commit(); } r_CurrentBattleID = null; }
void ProcessSecondStage(ApiData rpData) { foreach (FriendShip rParticipant in Participants.FriendMain) rParticipant.IsMVP = false; if (Participants.FriendEscort != null) foreach (FriendShip rParticipant in Participants.FriendEscort) rParticipant.IsMVP = false; switch (rpData.Api) { case "api_req_battle_midnight/battle": case "api_req_practice/midnight_battle": Second = new NightNormalStage(this, rpData); break; case "api_req_combined_battle/midnight_battle": Second = new CombinedFleetNightNormalStage(this, rpData); break; } Second.Process(rpData); Result.Update(First, Second); CurrentStage = Second; OnPropertyChanged(nameof(Second)); OnPropertyChanged(nameof(CurrentStage)); }
void ProcessSecondStage(ApiData rpData) { switch (rpData.Api) { case "api_req_battle_midnight/battle": case "api_req_practice/midnight_battle": Second = new NightNormalStage(this, rpData); break; case "api_req_combined_battle/midnight_battle": Second = new CombinedFleetNightNormalStage(this, rpData); break; } Second.Process(rpData); InheritFromPreviousStage(Second); Second.ProcessMVP(); Result.Update(First, Second); CurrentStage = Second; OnPropertyChanged(nameof(Second)); OnPropertyChanged(nameof(CurrentStage)); }
void SetFormationAndEngagementForm(ApiData rpData) { var rFormationRawData = rpData.Data as IRawFormationAndEngagementForm; FriendFormation = (Formation)rFormationRawData.FormationAndEngagementForm[0]; EnemyFormation = (Formation)rFormationRawData.FormationAndEngagementForm[1]; EngagementForm = (EngagementForm)rFormationRawData.FormationAndEngagementForm[2]; OnPropertyChanged(nameof(FriendFormation)); OnPropertyChanged(nameof(EnemyFormation)); OnPropertyChanged(nameof(EngagementForm)); }
void StartSortie(ApiData rpData) { var rSortie = KanColleGame.Current.Sortie; var rMap = rSortie.Map; r_CurrentSortieID = rSortie.ID; using (var rCommand = Connection.CreateCommand()) { rCommand.CommandText = "BEGIN TRANSACTION; " + "INSERT OR IGNORE INTO sortie_map(id, is_event_map) VALUES(@map_id, @is_event_map);" + "INSERT INTO sortie(id, map) VALUES(@sortie_id, @map_id);" + "COMMIT;"; rCommand.Parameters.AddWithValue("@map_id", rMap.ID); rCommand.Parameters.AddWithValue("@sortie_id", rSortie.ID); rCommand.Parameters.AddWithValue("@is_event_map", rMap.IsEventMap); rCommand.ExecuteNonQuery(); } r_NodeSubscription = Observable.FromEventPattern<PropertyChangedEventArgs>(rSortie, nameof(rSortie.PropertyChanged)) .Where(r => r.EventArgs.PropertyName == nameof(rSortie.Cell)) .Subscribe(_ => InsertExplorationRecord(KanColleGame.Current.Sortie)); }
// TODO _currentMinerReadStatus public override async Task <ApiData> GetSummaryAsync() { var ad = new ApiData(MiningSetup.CurrentAlgorithmType); var resp = await GetApiDataAsync(ApiPort, "summary"); if (resp == null) { CurrentMinerReadStatus = MinerApiReadStatus.NONE; return(null); } //// sgminer debug log //Helpers.ConsolePrint("sgminer-DEBUG_resp", resp); try { // Checks if all the GPUs are Alive first var resp2 = await GetApiDataAsync(ApiPort, "devs"); if (resp2 == null) { CurrentMinerReadStatus = MinerApiReadStatus.NONE; return(null); } //// sgminer debug log //Helpers.ConsolePrint("sgminer-DEBUG_resp2", resp2); var checkGpuStatus = resp2.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); for (var i = 1; i < checkGpuStatus.Length - 1; i++) { if (checkGpuStatus[i].Contains("Enabled=Y") && !checkGpuStatus[i].Contains("Status=Alive")) { Helpers.ConsolePrint(MinerTag(), ProcessTag() + " GPU " + i + ": Sick/Dead/NoStart/Initialising/Disabled/Rejecting/Unknown"); CurrentMinerReadStatus = MinerApiReadStatus.WAIT; return(null); } } var resps = resp.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); if (resps[1].Contains("SUMMARY")) { var data = resps[1].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); // Get miner's current total speed var speed = data[4].Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries); // Get miner's current total MH var totalMH = double.Parse(data[18].Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries)[1], new CultureInfo("en-US")); ad.Speed = double.Parse(speed[1]) * 1000; if (totalMH <= PreviousTotalMH) { Helpers.ConsolePrint(MinerTag(), ProcessTag() + " SGMiner might be stuck as no new hashes are being produced"); Helpers.ConsolePrint(MinerTag(), ProcessTag() + " Prev Total MH: " + PreviousTotalMH + " .. Current Total MH: " + totalMH); CurrentMinerReadStatus = MinerApiReadStatus.NONE; return(null); } PreviousTotalMH = totalMH; } else { ad.Speed = 0; } } catch { CurrentMinerReadStatus = MinerApiReadStatus.NONE; return(null); } CurrentMinerReadStatus = MinerApiReadStatus.GOT_READ; // check if speed zero if (ad.Speed == 0) { CurrentMinerReadStatus = MinerApiReadStatus.READ_SPEED_ZERO; } return(ad); }
public Task GetShipInfo(ApiResponse response, ApiData data) => ForwardRequest("getShipInfo", response, data);
private void MinuteCandleByTicks() { // 1분봉 3개를 기준으로 이전 시가 에서 현재 금액 등낙률을 가져온다. // 등낙률 0.5% 이상이 되면 오르면 팔고/ 내리면 산다. // 거래시 보유 현금, 보유 코인의 절반을 거래하되 거래 금액이 만원 미만인 경우 전체 금액으로 거래한다. var algIdx = cmbAlgorithm.SelectedIndex; var idx = (algIdx > 0) ? algIdx : Convert.ToInt32(txtMinute.Text); var candleType = BotSetting.CandleTypes[idx]; var candles = ApiData.getCandle <List <Candle> >(CoinName, candleType, 3); var prevCandle = candles.Last(); // 시가 봉 var currCandle = candles.First(); // 현재가 봉 var currPrice = currCandle.Close; var prevPrice = prevCandle.Close; var orderChance = GetOrderChance(ApiData, CoinName, currPrice); //var ask = orderChance["ask_account"]; //var bid = orderChance["bid_account"]; var krwBalance = orderChance.KRWBalance; // 보유 현금 var coinVol = orderChance.CoinVol; // 보유 코인 수량 var avgPrice = orderChance.AvgBuyPrice; // 매수 평단가 var coinPrice = orderChance.CoinBalance; // 보유 코인 금액 //var upRatio = (currPrice - avgPrice) / currPrice * 100; // 평단 대비 상승폭 (%) //var downRatio = (currPrice - prevPrice) / currPrice * 100; // 현재가 대비 하락폭 (%) var ratio = (currPrice - prevPrice) / currPrice * 100; // 등락폭 (%) var tradeRate = Convert.ToDouble(txtTradeRate.Text) / 100D; // 거래 비중 (%) var result = null as JObject; // 거래 결과 //txtKRW.Text = krwBalance.ToString("N0"); //txtCoinBalance.Text = coinPrice.ToString("N0"); Debug.WriteLine("이전가: {0:N0}, 현재가 {1:N0}, ratio : {2:F4}%", prevPrice, currPrice, ratio); WriteLog("이전가: {0:N0}, 현재가 {1:N0}, ratio : {2:F4}%", prevPrice, currPrice, ratio); try { if (avgPrice + (2 * (avgPrice * Rate / 100)) <= currPrice && coinPrice >= 5000) { // 현재가가 평단가보다 등락폭 2배 이상 올랐을때 전량 매도 var vol = coinVol; vol = Math.Truncate(vol * 100000) / 100000; Debug.WriteLine("#### {2} ALL SELL : 금액 {0:N0}, 수량 {1:F6}", vol * currPrice, vol, CoinName); WriteLog("#### {2} ALL SELL : 금액 {0:N0}, 수량 {1:F6}", vol * currPrice, vol, CoinName); result = React.executeDeal(false, false, CoinName, vol, 0, 0); LastSellDate = DateTime.Now; } else if (ratio >= Rate && coinPrice >= 5000 && ((DateTime.Now - LastSellDate).TotalMinutes >= idx || ratio >= Rate * 1.5)) { // 올랐을때 코인 금액 절반 팔기 var vol = (coinPrice * tradeRate) > 5000 ? coinVol * tradeRate : coinVol; vol = Math.Truncate(vol * 100000) / 100000; Debug.WriteLine("#### {2} SELL : 금액 {0:N0}, 수량 {1:F6}", vol * currPrice, vol, CoinName); WriteLog("#### {2} SELL : 금액 {0:N0}, 수량 {1:F6}", vol * currPrice, vol, CoinName); result = React.executeDeal(false, false, CoinName, vol, 0, 0); LastSellDate = DateTime.Now; } else if (ratio <= -(Rate * 1.2) && krwBalance > 5000 && (DateTime.Now - LastBuyDate).TotalMinutes >= idx) { // 1.2배 내렸을때 보유 현금 절반으로 코인 사기 var total = (krwBalance * tradeRate) > 5000 ? krwBalance * tradeRate : krwBalance; total = Math.Truncate(total * 1000) / 1000; Debug.WriteLine("#### {2} BUY : 금액 {0:N0}, 수량 {1:F6}", total, total / currPrice, CoinName); WriteLog("#### {2} BUY : 금액 {0:N0}, 수량 {1:F6}", total, total / currPrice, CoinName); result = React.executeDeal(true, false, CoinName, 0, 0, total); LastBuyDate = DateTime.Now; } } catch (Exception ex) { Debug.WriteLine(ex); WriteLog(ex.StackTrace); } orderChance = GetOrderChance(ApiData, CoinName, currPrice); if (result != null) { Debug.WriteLine("#### RESULT : {0}", result.ToString()); WriteLog("#### RESULT : {0}", result.ToString()); } }
public Task Scan(ApiResponse response, ApiData data) => ForwardRequest("scan", response, data);
public override async Task <ApiData> GetMinerStatsDataAsync() { var api = new ApiData(); try { var result = await _http.GetStringAsync($"http://127.0.0.1:{_apiPort}/api/v1/status"); var summary = JsonConvert.DeserializeObject <JsonApiResponse>(result); var perDeviceSpeedInfo = new Dictionary <string, IReadOnlyList <AlgorithmTypeSpeedPair> >(); var perDevicePowerInfo = new Dictionary <string, int>(); var totalSpeed = 0d; var totalSpeed2 = 0d; var totalPowerUsage = 0; var apiDevices = summary.miner.devices; foreach (var miningPair in _miningPairs) { var deviceUUID = miningPair.Device.UUID; var minerID = _mappedIDs[deviceUUID]; var apiDevice = apiDevices.Find(apiDev => apiDev.id == minerID); if (apiDevice == null) { continue; } totalSpeed += apiDevice.hashrate_raw; totalSpeed2 += apiDevice.hashrate2_raw; var kPower = (int)apiDevice.power * 1000; totalPowerUsage += kPower; if (_algorithmSecondType == AlgorithmType.NONE) { perDeviceSpeedInfo.Add(deviceUUID, new List <AlgorithmTypeSpeedPair> { new AlgorithmTypeSpeedPair(_algorithmType, apiDevice.hashrate_raw * (1 - DevFee * 0.01)) }); } else { perDeviceSpeedInfo.Add(deviceUUID, new List <AlgorithmTypeSpeedPair> { new AlgorithmTypeSpeedPair(_algorithmType, apiDevice.hashrate_raw * (1 - DevFee * 0.01)), new AlgorithmTypeSpeedPair(_algorithmSecondType, apiDevice.hashrate2_raw * (1 - DevFee * 0.01)) }); } perDevicePowerInfo.Add(deviceUUID, kPower); } if (_algorithmSecondType == AlgorithmType.NONE) { api.AlgorithmSpeedsTotal = new List <AlgorithmTypeSpeedPair> { new AlgorithmTypeSpeedPair(_algorithmType, totalSpeed * (1 - DevFee * 0.01)) }; } else { api.AlgorithmSpeedsTotal = new List <AlgorithmTypeSpeedPair> { new AlgorithmTypeSpeedPair(_algorithmType, totalSpeed * (1 - DevFee * 0.01)), new AlgorithmTypeSpeedPair(_algorithmSecondType, totalSpeed2 * (1 - DevFee * 0.01)) }; } api.PowerUsageTotal = totalPowerUsage; api.AlgorithmSpeedsPerDevice = perDeviceSpeedInfo; api.PowerUsagePerDevice = perDevicePowerInfo; } catch (Exception e) { Logger.Error(_logGroup, $"Error occured while getting API stats: {e.Message}"); } return(api); }
public Task Shield(ApiResponse response, ApiData data) => ForwardRequest("shield", response, data);
void Process(ApiData rpData) { if (rpData.Api != "api_req_battle_midnight/battle" && rpData.Api != "api_req_combined_battle/midnight_battle") UpdateCount(); }
public Task Shoot(ApiResponse response, ApiData data) => ForwardRequest("shoot", response, data);
private void PointHalfStrategy() { // 1분봉 3개를 기준으로 이전 시가 에서 현재 금액 등낙률을 가져온다. // 등낙률 0.5% 이상이 되면 오르면 팔고/ 내리면 산다. // 거래시 보유 현금, 보유 코인의 절반을 거래하되 거래 금액이 만원 미만인 경우 전체 금액으로 거래한다. var candles = ApiData.getCandle <List <Candle> >(CoinName, CandleType, CandleCount); var prevCandle = candles[2]; // 시가 봉 var currCandle = candles[0]; // 현재가 봉 var currPrice = currCandle.Close; var prevPrice = prevCandle.Close; var orderChance = ApiData.getOrdersChance(CoinName); var ask = orderChance["ask_account"]; var bid = orderChance["bid_account"]; var krwBalance = bid.Value <double>("balance"); // 보유 현금 var coinVol = ask.Value <double>("balance"); // 보유 코인 수량 var avgPrice = (coinVol * currPrice < 5000) ? currPrice : ask.Value <double>("avg_buy_price"); // 매수 평단가 var coinPrice = currPrice * coinVol; // 보유 코인 금액 var upRatio = (currPrice - avgPrice) / currPrice * 100; // 평단 대비 상승폭 (%) var downRatio = (currPrice - prevPrice) / currPrice * 100; // 현재가 대비 하락폭 (%) var result = null as JObject; // 거래 결과 txtKRW.Text = krwBalance.ToString("N0"); txtCoinBalance.Text = coinPrice.ToString("N6"); Debug.WriteLine("upRatio : {0}, downRatio {1}", upRatio, downRatio); WriteLog("upRatio : {0}, downRatio {1}", upRatio, downRatio); //try //{ // if (upRatio >= TriggerRatio && coinPrice > 5000) // { // // 올랐을때 코인 금액 절반 팔기 // var vol = (coinPrice / 2) > 5000 ? coinVol / 2 : coinVol; // vol = Math.Truncate(vol * 100000) / 100000; // Debug.WriteLine("#### {2} SELL : 금액 {0}, 수량 {1}", vol * currPrice, vol, CoinName); // WriteLog("#### {2} SELL : 금액 {0}, 수량 {1}", vol * currPrice, vol, CoinName); // result = React.executeDeal(false, false, CoinName, vol, 0, 0); // } // else if (downRatio <= -(TriggerRatio) && krwBalance > 5000) // { // // 내렸을때 보유 현금 절반으로 코인 사기 // var total = (krwBalance / 2) > 5000 ? krwBalance / 2 : krwBalance; // total = Math.Truncate(total * 1000) / 1000; // Debug.WriteLine("#### {2} BUY : 금액 {0}, 수량 {1}", total, total / currPrice, CoinName); // WriteLog("#### {2} BUY : 금액 {0}, 수량 {1}", total, total / currPrice, CoinName); // result = React.executeDeal(true, false, CoinName, 0, 0, total); // } //} //catch (Exception ex) //{ // Debug.WriteLine(ex); // WriteLog(ex.StackTrace); //} orderChance = ApiData.getOrdersChance(CoinName); ask = orderChance["ask_account"]; bid = orderChance["bid_account"]; krwBalance = bid.Value <double>("balance"); // 보유 현금 coinVol = ask.Value <double>("balance"); // 보유 코인 수량 coinPrice = currPrice * coinVol; // 보유 코인 금액 txtKRW.Text = krwBalance.ToString("N0"); txtCoinBalance.Text = coinPrice.ToString("N6"); //if (result != null) //{ // Debug.WriteLine("#### RESULT : {0}", result.ToString()); // WriteLog("#### RESULT : {0}", result.ToString()); //} }
/// <summary> /// /// </summary> /// <param name="xe"></param> public override void Load(XElement xe) { mData = new ApiData(); mData.LoadFromXML(xe); }
private void MinuteCandleByTicks() { // 설정값 var coinName = Coin.Ticker; var candleType = CandleType.Name; var candleCount = CandleCount; //var triggerRate = Rate; var feeRate = FeeRate; //var tradeRate = TradeRate; var profitRate = ProfitRate; // 해당 코인 보유금액이 있으면 매도 없으면 매수 var candles = ApiData.getCandle <List <Candle> >(coinName, candleType, candleCount); // 캔들 조회 var currCandle = candles.First(); // 현재 캔들 var currPrice = currCandle.Close; // 현재가 var orderChance = GetOrderChance(ApiData, coinName, currPrice); // 주문 가능 정보 var coinPrice = orderChance.CoinBalance * currPrice; // 코인 보유금 var krwBalance = orderChance.KRWBalance; // 보유 현금 var coinVol = orderChance.CoinVol; // 보유 코인 수량 var avgPrice = orderChance.AvgBuyPrice; // 매수 평단가 var minTradeKRW = Settings.Default.minTradeKRW; // 최소 거래 금액 // 분봉 N개를 기준으로 이전 시가 에서 현재 금액 등낙률을 가져온다. var prevCandle = candles[1]; // 직전 캔들 var lastCandle = candles.Last(); // 마지막 캔들 var prevPrice = prevCandle.Close; // 직전종가 var startPrice = lastCandle.Open; // 마지막 캔들 시작가 var change = (currPrice - prevPrice); // 변동가 var currentRate = (change / currPrice) * 100; // 등락율 var downChange = (startPrice - currPrice); // 상승전 변동가 var downRate = (downChange / startPrice) * 100; // 상승전 하락율 var profit = (currPrice - avgPrice); // 수익 var tradeProfitRate = (profit / avgPrice) * 100; // 수익율 var result = null as JObject; var args = new object[] { coinName, currPrice, prevPrice, startPrice, currentRate, downRate }; WriteLog("{0} : 현재가 {1:N0}, 이전가 {2:N0}, 시작가 {3:N0}, 직전등락폭 {4:F6}, 하락폭 {5:F6}", args); if (StartKRW < minTradeKRW && krwBalance > minTradeKRW && coinPrice < minTradeKRW) { // 거래 시작 금액 StartKRW = krwBalance; } try { if (coinPrice <= minTradeKRW && krwBalance <= minTradeKRW) { // 보유현금과 보유 코인이 최소 거래금액 보다 적으면 거래 없음 WriteLog("#### 거래 불가 : 보유현금 {0}, 코인보유금 {1}, 최소 거래 금액 {2},", krwBalance, coinPrice, minTradeKRW); } else if (krwBalance > minTradeKRW && downRate >= profitRate + (feeRate * 2) && currentRate >= (feeRate * 2)) { // BUY // 보유현금이 최소 거래금액 보다 많음 // 수익율 초과하여 떨어지다 수수료율 2배 이상 상승 했을때 거래비율 만큼 산다. var total = Math.Truncate(krwBalance * 1000) / 1000; result = React.executeDeal(true, false, coinName, 0, 0, total); LastBuyDate = DateTime.Now; WriteLog("#### {0} BUY : 금액 {1:N0}, 수량 {2:F6}", coinName, total, total / currPrice); } else if (krwBalance > minTradeKRW && (tradeProfitRate <= profitRate - (feeRate * 2) || tradeProfitRate >= profitRate + (feeRate * 2))) { // SELL // 코인평가금 최소 거래금액 보다 많음 // 현재가가 평단가 보다 (수익율 - 수료율 * 2) 이하일때 전체 매도 // 현재가가 평단가 보다 (수익율 + 수료율 * 2) 이상일때 전체 매도 var vol = coinVol; vol = Math.Truncate(vol * 100000) / 100000; result = React.executeDeal(false, false, coinName, vol, 0, 0); LastSellDate = DateTime.Now; WriteLog("#### {0} SELL : 금액 {1:N0}, 수량 {2:F6}", coinName, vol * currPrice, vol); } } catch (Exception ex) { WriteLog(ex.StackTrace); } if (result != null) { var chance = GetOrderChance(ApiData, coinName, currPrice); var totalKrw = chance.KRWBalance + chance.CoinBalance; var krwProfit = totalKrw - StartKRW; var krwProfitRate = krwProfit / StartKRW * 100; var profits = new object[] { coinName, StartKRW, totalKrw, krwProfit, krwProfitRate }; WriteLog("#### RESULT : {0}", result.ToString()); WriteLog("#### {0} 수익 : 거래시작금액 {1:N0}, 현재평가 금액 {2:N0}, 수익금액 {3:N0}, 수익율 {4F6}", profits); } }
public ManagerForm(LogCache logCache, ApiData apiData) { LogCache = logCache ?? throw new ArgumentNullException(nameof(logCache)); ApiData = apiData ?? throw new ArgumentNullException(nameof(apiData)); // Background processors var dpsReportUploader = new DpsReportUploader(); UploadProcessor = new UploadProcessor(dpsReportUploader, LogCache); ApiProcessor = new ApiProcessor(ApiData, new Gw2Client()); LogDataProcessor = new LogDataProcessor(LogCache, ApiProcessor, LogAnalytics); LogNameProvider = new TranslatedLogNameProvider(GameLanguage.English); Filters = new LogFilters(new SettingsFilters()); Filters.PropertyChanged += (sender, args) => logsFiltered.Refresh(); if (Settings.UseGW2Api) { ApiProcessor.StartBackgroundTask(); } Settings.UseGW2ApiChanged += (sender, args) => { if (Settings.UseGW2Api) { ApiProcessor.StartBackgroundTask(); } else { ApiProcessor.StopBackgroundTask(); } }; Settings.DpsReportDomainChanged += (sender, args) => { dpsReportUploader.Domain = Settings.DpsReportDomain; }; // Form layout Icon = Resources.GetProgramIcon(); Title = "arcdps Log Manager"; ClientSize = new Size(1300, 768); var formLayout = new DynamicLayout(); Content = formLayout; Menu = ConstructMenuBar(); formLayout.BeginVertical(new Padding(5), yscale: false); { formLayout.Add(ConstructMainSplitter(), yscale: true); formLayout.Add(ConstructStatusPanel()); } formLayout.EndVertical(); // Event handlers ApiProcessor.Processed += (sender, args) => { bool last = args.CurrentScheduledItems == 0; if (last) { ApiData.SaveDataToFile(); } }; Settings.LogRootPathChanged += (sender, args) => Application.Instance.Invoke(ReloadLogs); Shown += (sender, args) => ReloadLogs(); Closing += (sender, args) => { if (LogCache?.ChangedSinceLastSave ?? false) { LogCache?.SaveToFile(); } ApiData?.SaveDataToFile(); }; LogCollectionsRecreated += (sender, args) => { logsFiltered.Filter = Filters.FilterLog; logsFiltered.Refresh(); }; LogSearchFinished += (sender, args) => { var updates = LogDataUpdater.GetUpdates(logs).ToList(); if (updates.Count > 0) { new UpdateDialog(LogDataProcessor, updates).ShowModal(this); } }; // Collection initialization RecreateLogCollections(new ObservableCollection <LogData>(logs)); }
private void Timer_Tick(object sender, EventArgs e) { var KRWAccount = ApiData.getAsset().Where(x => "KRW".Equals(x.Value <string>("currency"))).First(); Thread.Sleep(100); var krwBalance = KRWAccount.Value <double>("balance"); // 보유 현금 var candles = ApiData.getCandle <List <Candle> >(CoinName, CandleType, CandleCount); Thread.Sleep(100); var prevCandle = candles[2]; var currCandle = candles[0]; var currPrice = currCandle.Close; var prevPrice = prevCandle.Close; var orderChance = ApiData.getOrdersChance(CoinName); Thread.Sleep(100); var ask = orderChance["ask_account"]; var coinVol = ask.Value <double>("balance"); // 보유 코인 수량 var avgPrice = (coinVol * currPrice < 5000) ? currPrice : ask.Value <double>("avg_buy_price"); // 매수 평단가 var coinPrice = avgPrice * coinVol; // 보유 코인 금액 var upRatio = (currPrice - avgPrice) / currPrice * 100; // 평단 대비 상승폭 (%) var downRatio = (currPrice - prevPrice) / currPrice * 100; // 현재가 대비 하락폭 (%) var result = null as JObject; // 거래 결과 Debug.WriteLine("upRatio : {0}, downRatio {1}", upRatio, downRatio); WriteLog("upRatio : {0}, downRatio {1}", upRatio, downRatio); try { if (upRatio >= TriggerRatio && coinPrice > 5000) { // 올랐을때 코인 금액 절반 팔기 var vol = (coinPrice / 2) > 5000 ? coinVol / 2 : coinVol; vol = Math.Truncate(vol * 100000) / 100000; Debug.WriteLine("#### {2} SELL : 금액 {0}, 수량 {1}", vol * currPrice, vol, CoinName); WriteLog("#### {2} SELL : 금액 {0}, 수량 {1}", vol * currPrice, vol, CoinName); result = React.executeDeal(false, false, CoinName, vol, 0, 0); } else if (downRatio <= -(TriggerRatio) && krwBalance > 5000) { // 내렸을때 보유 현금 절반으로 코인 사기 var total = (krwBalance / 2) > 5000 ? krwBalance / 2 : krwBalance; total = Math.Truncate(total * 1000) / 1000; Debug.WriteLine("#### {2} BUY : 금액 {0}, 수량 {1}", total, total / currPrice, CoinName); WriteLog("#### {2} BUY : 금액 {0}, 수량 {1}", total, total / currPrice, CoinName); result = React.executeDeal(true, false, CoinName, 0, 0, total); } } catch (Exception ex) { Debug.WriteLine(ex); WriteLog(ex.StackTrace); } if (result != null) { Debug.WriteLine("#### RESULT : {0}", result.ToString()); WriteLog("#### RESULT : {0}", result.ToString()); } }
public override async Task <ApiData> GetSummaryAsync() { CurrentMinerReadStatus = MinerApiReadStatus.NONE; var ad = new ApiData(MiningSetup.CurrentAlgorithmType, MiningSetup.CurrentSecondaryAlgorithmType); var elapsedSeconds = DateTime.Now.Subtract(_started).Seconds; if (elapsedSeconds < 15 && firstStart) { return(ad); } firstStart = false; JsonApiResponse resp = null; try { var bytesToSend = Encoding.ASCII.GetBytes("{\"id\":0,\"jsonrpc\":\"2.0\",\"method\":\"miner_getstat1\"}\n"); using (var client = new TcpClient("127.0.0.1", ApiPort)) using (var nwStream = client.GetStream()) { await nwStream.WriteAsync(bytesToSend, 0, bytesToSend.Length); var bytesToRead = new byte[client.ReceiveBufferSize]; var bytesRead = await nwStream.ReadAsync(bytesToRead, 0, client.ReceiveBufferSize); var respStr = Encoding.ASCII.GetString(bytesToRead, 0, bytesRead); // Helpers.ConsolePrint(MinerTag(), "respStr: " + respStr); resp = JsonConvert.DeserializeObject <JsonApiResponse>(respStr, Globals.JsonSettings); } } catch (Exception ex) { Helpers.ConsolePrint(MinerTag(), "GetSummary exception: " + ex.Message); } if (resp != null && resp.error == null) { var speeds = resp.result[3].Split(';'); ad.Speed = 0; ad.SecondarySpeed = 0; foreach (var speed in speeds) { double tmpSpeed; try { tmpSpeed = double.Parse(speed, CultureInfo.InvariantCulture); } catch { tmpSpeed = 0; } ad.Speed += tmpSpeed; } CurrentMinerReadStatus = MinerApiReadStatus.GOT_READ; if (ad.Speed == 0) { CurrentMinerReadStatus = MinerApiReadStatus.READ_SPEED_ZERO; } } //Thread.Sleep(200); return(ad); }
private static void UpdateDeviceMiningStats(ApiData apiData, string minerUUID, string minerName, string groupKey, string deviceUuid, Dictionary <AlgorithmType, double> payingRates) { DeviceMiningStats stat; if (_devicesMiningStats.TryGetValue(deviceUuid, out stat) == false) { // create if it doesn't exist stat = new DeviceMiningStats { DeviceUUID = deviceUuid }; _devicesMiningStats[deviceUuid] = stat; } stat.Clear(); // re-set miner name and group key stat.MinerName = minerName; stat.GroupKey = groupKey; // update stat var deviceSpeedsInfo = apiData.AlgorithmSpeedsPerDevice .Where(pair => pair.Key == deviceUuid) .Select(pair => pair.Value) .FirstOrDefault(); if (deviceSpeedsInfo != null) { foreach (var speedInfo in deviceSpeedsInfo) { stat.Speeds.Add((speedInfo.AlgorithmType, speedInfo.Speed)); if (payingRates.TryGetValue(speedInfo.AlgorithmType, out var paying) == false) { continue; } var payingRate = paying * speedInfo.Speed * 0.000000001; stat.Rates.Add((speedInfo.AlgorithmType, payingRate)); } } var devicePowerUsageApi = (double)apiData.PowerUsagePerDevice .Where(pair => pair.Key == deviceUuid) .Select(pair => pair.Value) .FirstOrDefault(); stat.PowerUsageAPI = devicePowerUsageApi / 1000d; // TODO Globals var dev = AvailableDevices.GetDeviceWithUuid(deviceUuid); if (dev != null) { stat.PowerUsageDeviceReading = dev.PowerUsage; var algo = dev.GetAlgorithm(minerUUID, apiData.AlgorithmSpeedsPerDevice[dev.Uuid].Select(info => info.AlgorithmType).ToArray()); stat.PowerUsageAlgorithmSetting = algo == null ? 0d : algo.PowerUsage; } lock (_devMiningStats) { var index = _devMiningStats.IndexOf(stat); if (index < 0) { _devMiningStats.Add(stat); } else { _devMiningStats[index] = stat; } } //// TODO enable StabilityAnalyzer //// TODO not the best place but here is where we get our per device speeds //var algorithmName = string.Join("+", stat.Speeds.Select(speedPair => Enum.GetName(typeof(AlgorithmType), speedPair.type))); //var algorithmStringID = $"{algorithmName}_{minerUUID}"; //var speedID = $"{deviceUuid}-{algorithmStringID}"; //var primarySpeed = stat.Speeds.Count > 0 ? stat.Speeds[0].speed : 0d; //var secondarySpeed = stat.Speeds.Count > 1 ? stat.Speeds[1].speed : 0d; //var miningSpeed = new BenchmarkingAnalyzer.MiningSpeed //{ // PrimarySpeed = primarySpeed, // SecondarySpeed = secondarySpeed, // Timestamp = DateTime.Now //}; //BenchmarkingAnalyzer.UpdateMiningSpeeds(speedID, miningSpeed); }
private bool ValidateApiFiles(ApiData shippedData, ApiData unshippedData, out List<Diagnostic> errors) { errors = new List<Diagnostic>(); if (shippedData.RemovedApiList.Length > 0) { errors.Add(Diagnostic.Create(PublicApiFilesInvalid, Location.None, InvalidReasonShippedCantHaveRemoved)); } var publicApiMap = new Dictionary<string, ApiLine>(StringComparer.Ordinal); ValidateApiList(publicApiMap, shippedData.ApiList, errors); ValidateApiList(publicApiMap, unshippedData.ApiList, errors); return errors.Count == 0; }
private async Task MinerSpeedsLoop(CancellationTokenSource ct) { Logger.Info("EXCAVATOR-MinerSpeedsLoop", $"STARTING"); try { var workers = string.Join(",", _miningPairs.Select((_, i) => $@"""{i}""")); var workersReset = @"{""id"":1,""method"":""workers.reset"",""params"":[__WORKERS__]}".Replace("__WORKERS__", workers); Func <bool> isActive = () => !ct.Token.IsCancellationRequested; var lastSuccessfulSpeeds = DateTime.UtcNow; while (isActive()) { var elapsed = DateTime.UtcNow - lastSuccessfulSpeeds; if (elapsed >= TimeSpan.FromSeconds(50)) { Logger.Info("EXCAVATOR-MinerSpeedsLoop", $"Restaring excavator due to speed anomaly"); //_ = await ExecuteCommand(@"{""id"":1,""method"":""quit"",""params"":[]}"); #warning if no nhm watchdog it will never restart 'nhms' await StopMiningTask(); } try { _ = await ExecuteCommand(workersReset, ct.Token); if (isActive()) { await ExcavatorTaskHelpers.TryDelay(TimeSpan.FromSeconds(30), ct.Token); } // get speeds var ad = await GetMinerStatsDataAsyncPrivate(ct.Token); LastApiData = ad; if (IsSpeedOk(ad)) { lastSuccessfulSpeeds = DateTime.UtcNow; } // speed print and reset _ = await ExecuteCommand(@"{""id"":1,""method"":""worker.print.efficiencies"",""params"":[]}", ct.Token); } catch (TaskCanceledException) { break; } catch (Exception e) { Logger.Error("EXCAVATOR-MinerSpeedsLoop", $"Error {e}"); } } Logger.Info("EXCAVATOR-MinerSpeedsLoop", $"EXIT WHILE"); } catch (TaskCanceledException) { } catch (Exception ex) { Logger.Error("EXCAVATOR-API_LOOP", $"error {ex}"); } finally { ct.Dispose(); } }
void ProcessPracticeFirstStage(ApiData rpData) { var rParticipantFleet = KanColleGame.Current.Port.Fleets[int.Parse(rpData.Parameters["api_deck_id"])]; var rPractice = (PracticeInfo)KanColleGame.Current.Sortie; var rOpponent = rPractice.Opponent; r_CurrentBattleID = rPractice.Battle.ID; using (var rTransaction = Connection.BeginTransaction()) using (var rCommand = Connection.CreateCommand()) { var rCommandTextBuilder = new StringBuilder(1024); rCommandTextBuilder.Append("INSERT OR IGNORE INTO practice_opponent(id, name) VALUES(@opponent_id, @opponent_name);" + "INSERT OR IGNORE INTO practice_opponent_comment(id, comment) VALUES(@opponent_comment_id, @opponent_coment);" + "INSERT OR IGNORE INTO practice_opponent_fleet(id, name) VALUES(@opponent_fleet_name_id, @opponent_fleet_name);" + "INSERT INTO practice(id, opponent, opponent_level, opponent_experience, opponent_rank, opponent_comment, opponent_fleet) VALUES(@battle_id, @opponent_id, @opponent_level, @opponent_experience, @opponent_rank, @opponent_comment_id, @opponent_fleet_name_id);" + "INSERT INTO battle_detail.battle(id, first) VALUES(@battle_id, @first);"); rCommand.Parameters.AddWithValue("@opponent_id", rOpponent.RawData.ID); rCommand.Parameters.AddWithValue("@opponent_name", rOpponent.Name); rCommand.Parameters.AddWithValue("@opponent_comment_id", rOpponent.RawData.CommentID ?? -1); rCommand.Parameters.AddWithValue("@opponent_coment", rOpponent.Comment); rCommand.Parameters.AddWithValue("@opponent_fleet_name_id", rOpponent.RawData.FleetNameID ?? -1); rCommand.Parameters.AddWithValue("@opponent_fleet_name", rOpponent.FleetName); rCommand.Parameters.AddWithValue("@opponent_level", rOpponent.Level); rCommand.Parameters.AddWithValue("@opponent_experience", rOpponent.RawData.Experience[0]); rCommand.Parameters.AddWithValue("@opponent_rank", (int)rOpponent.Rank); rCommand.Parameters.AddWithValue("@battle_id", r_CurrentBattleID.Value); rCommand.Parameters.AddWithValue("@first", CompressJson(rpData.Json["api_data"])); ProcessParticipantFleet(rCommandTextBuilder, rParticipantFleet, ParticipantFleetType.Main); rCommand.CommandText = rCommandTextBuilder.ToString(); rCommand.ExecuteNonQuery(); rTransaction.Commit(); } }
private async Task <ApiData> GetSummaryAsync() { var apiData = new ApiData(); if (!IsUpdatingApi) { IsUpdatingApi = true; await _apiSemaphore.WaitAsync(); try { apiData = await _miner.GetMinerStatsDataAsync(); } catch (Exception e) { Logger.Error(MinerTag(), $"GetSummaryAsync error: {e.Message}"); } finally { IsUpdatingApi = false; _apiSemaphore.Release(); if (apiData.AlgorithmSpeedsPerDevice != null) { var anyNegative = apiData.AlgorithmSpeedsPerDevice.Any(apiDev => apiDev.Value.Any(kvp => kvp.speed < 0)); if (anyNegative) { await StopAsync(); } } } } UpdateApiTimestamp(apiData); // TODO workaround plugins should return this info // create empty stub if it is null if (apiData == null) { Logger.Debug(MinerTag(), "GetSummary returned null... Will create ZERO fallback"); apiData = new ApiData(); } if (apiData.AlgorithmSpeedsPerDevice == null) { apiData = new ApiData(); var perDevicePowerDict = new Dictionary <string, int>(); var perDeviceSpeedsDict = new Dictionary <string, IReadOnlyList <(AlgorithmType type, double speed)> >(); var perDeviceSpeeds = MiningPairs.Select(pair => (pair.Device.UUID, pair.Algorithm.IDs.Select(type => (type, 0d)))); foreach (var kvp in perDeviceSpeeds) { var uuid = kvp.Item1; // kvp.UUID compiler doesn't recognize ValueTypes lib??? perDeviceSpeedsDict[uuid] = kvp.Item2.ToList(); perDevicePowerDict[uuid] = 0; } apiData.AlgorithmSpeedsPerDevice = perDeviceSpeedsDict; apiData.PowerUsagePerDevice = perDevicePowerDict; apiData.PowerUsageTotal = 0; } else if (apiData.AlgorithmSpeedsPerDevice != null && apiData.PowerUsagePerDevice.Count == 0) { var perDevicePowerDict = new Dictionary <string, int>(); foreach (var kvp in MiningPairs) { var uuid = kvp.Device.UUID; perDevicePowerDict[uuid] = 0; } apiData.PowerUsagePerDevice = perDevicePowerDict; apiData.PowerUsageTotal = 0; } // TODO temporary here move it outside later MiningDataStats.UpdateGroup(apiData, _plugin.PluginUUID, _plugin.Name); return(apiData); }
private bool ValidateApiFiles(ApiData shippedData, ApiData unshippedData, out List<Diagnostic> list) { list = new List<Diagnostic>(); if (shippedData.RemovedApiList.Length > 0) { list.Add(Diagnostic.Create(PublicApiFilesInvalid, Location.None, InvalidReasonShippedCantHaveRemoved)); } return list.Count == 0; }
private void MinuteCandleByTicks() { // 설정값 var coinName = Coin.Ticker; var candleType = CandleType.Name; var candleCount = CandleCount; var feeRate = FeeRate; var tradeRate = TradeRate; var triggerRate = TriggerRate; // 캔들 갯수 많큼 캔들 가져오기 var candles = ApiData.getCandle <List <Candle> >(coinName, candleType, candleCount * 2); // 캔들 조회 (2배로 여유롭게) var currPrice = candles.First().Close; // 현재가 // 보유현금 및 주문 정보 var orderChance = ApiData.getOrdersChance(coinName); // 주문 가능 정보 var bid = orderChance["bid_account"]; var ask = orderChance["ask_account"]; var krwBalance = bid.Value <double>("balance"); // 보유 현금 var coinVol = ask.Value <double>("balance"); // 보유 코인 수량 var avgPrice = ask.Value <double>("avg_buy_price"); // 매수 평단가 var bidLock = bid.Value <double>("locked"); // 매수 대기 금액 var coinBuyBalance = avgPrice * coinVol; // 코인 매수금 var coinBalance = currPrice * coinVol; // 코인 평가금 var minTradeKRW = Settings.Default.minTradeKRW; // 최소 거래 금액 // 분봉 N개를 기준으로 직전 시가 에서 현재 금액 등낙률을 가져온다. //var prevCandle = candles[1]; // 직전 캔들 //var lastCandle = candles.Last(); // 마지막 캔들 var prevPrice = candles[1].Close; // 직전종가 var highPrice = candles.GetRange(1, candleCount - 1).Max(x => x.High); // 최고가 var triggerDownPrice = highPrice - (highPrice * (triggerRate + (feeRate * 2)) / 100); // 매수 하락 촉발가 var downRate = (currPrice - highPrice) / highPrice * 100; // 하락율 var triggerUpPrice = prevPrice + (prevPrice * ((triggerRate / candleCount + 1) + (feeRate * 2)) / 100); // 매수 반등 촉발가 var upRate = (currPrice - prevPrice) / prevPrice * 100; // 반등 상승율 var downUpRate = (-downRate / upRate); // 반등율 //var targetDownPrice = prevPrice + (prevPrice * (feeRate * 2) / 100); // 매수 목표가 WriteLog("currPrice {0:N0}, triggerDownPrice {1:N0}, triggerUpPrice {2:N0}, highPrice {3:N0}, prevPrice {4:N0}, downUpRate {5:N0}", currPrice, triggerDownPrice, triggerUpPrice, highPrice, prevPrice, downUpRate); //var changePrice = (currPrice - prevPrice); // 변동가 //var changeRate = (changePrice / currPrice) * 100; // 변동율 //var candlesChange = (currPrice - highPrice); // 캔들 변동가 //var candlesRate = (candlesChange / highPrice) * 100; // 캔들 변동율 //var profit = coinBalance - coinBuyBalance; // 수익 //var tradeProfitRate = (avgPrice == 0) ? 0D : (profit / avgPrice) * 100; // 수익율 //var targetProfit = coinBuyBalance + (coinBuyBalance * ((triggerRate / candleCount) + (feeRate * 2)) / 100); //var targetPrice = avgPrice + targetProfit; //var target = coinBuyPrice //var result = null as JObject; //var args = new object[] { coinName, currPrice, prevPrice, highPrice, changeRate, candlesRate, avgPrice, targetProfit }; var buyTs = DateTime.Now - LastBuyDate; var sellTs = DateTime.Now - LastSellDate; //var minutes = sellTs.TotalMinutes; //WriteCurrent("{0} : 현재가 {1:N0}, 직전가 {2:N0}, 시작가 {3:N0}, 직전등락폭 {4:F6}, 등락폭 {5:F6}, 평단가 {6:N0}, 목표가 {7:N0}", args); if (StartKRW < minTradeKRW && krwBalance > minTradeKRW && coinBalance < minTradeKRW) { // 거래 시작 금액 StartKRW = krwBalance; } try { if (coinBalance <= minTradeKRW && krwBalance <= minTradeKRW) { // 보유현금과 보유 코인이 최소 거래금액 보다 적으면 거래 없음 WriteLog("#### 거래 불가 : 보유현금 {0}, 코인보유금 {1}, 최소 거래 금액 {2},", krwBalance, coinBalance, minTradeKRW); } else if (krwBalance > minTradeKRW && // 보유 현금이 최소거래 금액 보다 크고 sellTs.TotalSeconds >= CandleType.Minute * 60 / 2 && // 매도 이후 분봉의 절반이상이 지나고 currPrice <= triggerDownPrice && currPrice >= triggerUpPrice && // 현재가가 촉발 금액 사이에서 반등하고 downUpRate <= candleCount * 2) // 반등율이 캔들갯수의 2배수가 넘지 않아야 함 { // BUY var total = ToOrderPrice(krwBalance); var avgBuyPrice = currPrice; //result = React.executeDeal(true, false, coinName, 0, 0, total); LastBuyDate = DateTime.Now; WriteLog("#### {0} BUY : 매수 평단가 {1:N0}, 매수금 {2:N0}, 수량 {2:F6}", coinName, avgBuyPrice, total, total / avgBuyPrice); } //else if (coinBalance > minTradeKRW // && (buyTs.TotalSeconds >= CandleType.Minute * 60 * candleCount / 2 // || targetProfit <= coinBalance)) //{ // // SELL // // 코인평가금 최소 거래금액 보다 많음 // // 분봉 하나의 시간이 지나면 시장가에 전체 매도 // // 현재가가 평단가 보다 (수익율/캔들수 + 수료율2배) 이상일때 전체 매도 // var vol = coinVol; // vol = Math.Truncate(vol * 100000) / 100000; // //result = React.executeDeal(false, false, coinName, vol, 0, 0); // LastSellDate = DateTime.Now; // WriteLog("#### {0} SELL : 금액 {1:N0}, 수량 {2:F6}", coinName, vol * currPrice, vol); //} } catch (Exception ex) { WriteLog(ex.StackTrace); } //if (result != null) //{ // var uuid = result.Value<string>("uuid"); // var coinProfit = GetOrderResult(ApiData, uuid, coinName, currPrice, StartKRW); // //WriteLog("#### RESULT : {0}", result.ToString()); // //var coinProfit = GetBalance(ApiData, coinName, StartKRW); // //txtProfitPrice.Text = coinProfit.KrwProfit.ToString("N0"); // //txtProfitRate.Text = coinProfit.KrwProfitRate.ToString("F6"); // var profits = new object[] { coinName, StartKRW, coinProfit.TotalBalance, coinProfit.KrwProfit, coinProfit.KrwProfitRate }; // WriteLog("#### {0} 수익 : 거래시작금액 {1:N0}, 현재평가 금액 {2:N0}, 수익금액 {3:N0}, 수익율 {4:F6}", profits); //} }
internal protected AerialAttackStage(BattleInfo rpOwner, ApiData rpData) : base(rpOwner) { var rRawData = rpData.Data as IAerialCombat; AerialAttack = new AerialCombatPhase(this, rRawData.AerialCombat, PhaseRound.First); }
public async Task SetPromotionStatusAsync( [FromBody] ChatMessage message) { Character newCharacter = null; CharacterLog charalog = null; CharacterLog senderCharalog = null; MapLog maplog = null; Town newTown = null; Town oldTown = null; CountryMessage commanders = null; IEnumerable <uint> oldTownCharacters = null; IEnumerable <uint> newTownCharacters = null; using (var repo = MainRepository.WithReadAndWrite()) { var system = await repo.System.GetAsync(); var chara = await repo.Character.GetByIdAsync(this.AuthData.CharacterId).GetOrErrorAsync(ErrorCode.CharacterNotFoundError); var old = await repo.ChatMessage.GetByIdAsync(message.Id).GetOrErrorAsync(ErrorCode.InvalidParameterError); var country = await repo.Country.GetAliveByIdAsync(chara.CountryId); if (country.HasData) { // 無所属以外は実行できない ErrorCode.InvalidOperationError.Throw(); } if (old.Type != ChatMessageType.Promotion) { // 登用文ではない ErrorCode.InvalidOperationError.Throw(); } if (message.Type == ChatMessageType.PromotionAccepted) { var sender = await repo.Character.GetByIdAsync(old.TypeData).GetOrErrorAsync(ErrorCode.CharacterNotFoundError); var senderCountry = await repo.Country.GetAliveByIdAsync(old.CharacterCountryId).GetOrErrorAsync(ErrorCode.CountryNotFoundError); if (senderCountry.IntEstablished + Config.CountryBattleStopDuring > system.IntGameDateTime) { var characterCount = await repo.Country.CountCharactersAsync(senderCountry.Id, true); if (characterCount >= Config.CountryJoinMaxOnLimited) { // 戦闘解除前の国に士官できない ErrorCode.CantJoinAtSuchCountryhError.Throw(); } } var blockActions = await repo.BlockAction.GetAvailableTypesAsync(chara.Id); if (blockActions.Contains(BlockActionType.StopJoin) && !system.IsWaitingReset) { ErrorCode.BlockedActionError.Throw(); } oldTown = await repo.Town.GetByIdAsync(chara.TownId).GetOrErrorAsync(ErrorCode.TownNotFoundError); newTown = await repo.Town.GetByIdAsync(senderCountry.CapitalTownId).GetOrErrorAsync(ErrorCode.TownNotFoundError); oldTownCharacters = (await repo.Town.GetCharactersWithIconAsync(oldTown.Id)).Select(c => c.Character.Id); newTownCharacters = (await repo.Town.GetCharactersWithIconAsync(newTown.Id)).Select(c => c.Character.Id); commanders = (await repo.Country.GetMessageAsync(senderCountry.Id, CountryMessageType.Commanders)).Data; var reinforcements = await repo.Reinforcement.GetByCharacterIdAsync(chara.Id); if (reinforcements.Any(r => r.Status == ReinforcementStatus.Active)) { ErrorCode.NotPermissionError.Throw(); } await CharacterService.ChangeTownAsync(repo, senderCountry.CapitalTownId, chara); await CharacterService.ChangeCountryAsync(repo, senderCountry.Id, new Character[] { chara, }); charalog = new CharacterLog { CharacterId = chara.Id, DateTime = DateTime.Now, GameDateTime = system.GameDateTime, Message = $"<character>{sender.Name}</character> の登用に応じ、 <country>{senderCountry.Name}</country> に仕官しました", }; senderCharalog = new CharacterLog { CharacterId = old.TypeData, DateTime = DateTime.Now, GameDateTime = system.GameDateTime, Message = $"<character>{chara.Name}</character> があなたの登用に応じ、 <country>{senderCountry.Name}</country> に仕官しました", }; maplog = new MapLog { Date = DateTime.Now, ApiGameDateTime = system.GameDateTime, IsImportant = false, EventType = EventType.PromotionAccepted, Message = $"<character>{chara.Name}</character> は <country>{senderCountry.Name}</country> に仕官しました", }; old.Character = new CharacterChatData(sender, null); old.ReceiverName = chara.Name; old.Type = message.Type; newCharacter = chara; } else if (message.Type == ChatMessageType.PromotionRefused) { var sender = await repo.Character.GetByIdAsync(old.TypeData).GetOrErrorAsync(ErrorCode.CharacterNotFoundError); charalog = new CharacterLog { CharacterId = chara.Id, DateTime = DateTime.Now, GameDateTime = system.GameDateTime, Message = $"<character>{sender.Name}</character> の登用を断りました", }; senderCharalog = new CharacterLog { CharacterId = old.TypeData, DateTime = DateTime.Now, GameDateTime = system.GameDateTime, Message = $"<character>{chara.Name}</character> は、あなたの登用を断りました", }; old.Character = new CharacterChatData(sender, null); old.ReceiverName = chara.Name; old.Type = message.Type; } else { ErrorCode.InvalidParameterError.Throw(); } if (maplog != null) { await repo.MapLog.AddAsync(maplog); } if (charalog != null) { await repo.Character.AddCharacterLogAsync(charalog); } if (senderCharalog != null) { await repo.Character.AddCharacterLogAsync(senderCharalog); } message = old; await repo.SaveChangesAsync(); } if (newCharacter != null) { StatusStreaming.Default.UpdateCache(new Character[] { newCharacter, }); await StatusStreaming.Default.SendCharacterAsync(ApiData.From(newCharacter), newCharacter.Id); } if (charalog != null) { await StatusStreaming.Default.SendCharacterAsync(ApiData.From(charalog), charalog.CharacterId); await StatusStreaming.Default.SendCharacterAsync(ApiData.From(message), charalog.CharacterId); } if (senderCharalog != null) { await StatusStreaming.Default.SendCharacterAsync(ApiData.From(senderCharalog), senderCharalog.CharacterId); await StatusStreaming.Default.SendCharacterAsync(ApiData.From(message), senderCharalog.CharacterId); } if (maplog != null) { await StatusStreaming.Default.SendAllAsync(ApiData.From(maplog)); await AnonymousStreaming.Default.SendAllAsync(ApiData.From(maplog)); } }
public static async Task <ApiData> GetMinerStatsDataAsync(int apiPort, IReadOnlyList <BaseDevice> miningDevices, string logGroup, double DevFee, double DualDevFee, params AlgorithmType[] algorithmTypes) { var ad = new ApiData(); var firstAlgoType = AlgorithmType.NONE; var secondAlgoType = AlgorithmType.NONE; bool isDual = algorithmTypes.Count() > 1; if (algorithmTypes.Count() > 0) { firstAlgoType = algorithmTypes[0]; } if (algorithmTypes.Count() > 1) { secondAlgoType = algorithmTypes[1]; } var totalSpeed = new List <(AlgorithmType type, double speed)>(); var perDeviceSpeedInfo = new Dictionary <string, IReadOnlyList <(AlgorithmType type, double speed)> >(); var perDevicePowerInfo = new Dictionary <string, int>(); JsonApiResponse resp = null; try { var bytesToSend = Encoding.ASCII.GetBytes(_jsonStatsApiCall); using (var client = new TcpClient("127.0.0.1", apiPort)) using (var nwStream = client.GetStream()) { await nwStream.WriteAsync(bytesToSend, 0, bytesToSend.Length); var bytesToRead = new byte[client.ReceiveBufferSize]; var bytesRead = await nwStream.ReadAsync(bytesToRead, 0, client.ReceiveBufferSize); var respStr = Encoding.ASCII.GetString(bytesToRead, 0, bytesRead); ad.ApiResponse = respStr; resp = JsonConvert.DeserializeObject <JsonApiResponse>(respStr); } if (resp != null && resp.error == null) { if (resp.result != null && resp.result.Count > 3) { var speeds = TransformSpeedsList(resp.result[3]); var hasSecond = isDual && resp.result.Count > 5; var secondarySpeeds = hasSecond ? TransformSpeedsList(resp.result[5]) : _emptySpeeds; var primaryTotalSpeed = 0d; var secondaryTotalSpeed = 0d; for (int i = 0; i < miningDevices.Count(); i++) { var dev = miningDevices[i]; var uuid = dev.UUID; var primaryCurrentSpeed = speeds.Count > i ? speeds[i] : 0d; var secondaryCurrentSpeed = secondarySpeeds.Count > i ? secondarySpeeds[i] : 0d; primaryTotalSpeed += primaryCurrentSpeed; secondaryTotalSpeed += secondaryCurrentSpeed; var perDeviceSpeeds = new List <(AlgorithmType type, double speed)>() { (firstAlgoType, primaryCurrentSpeed *(1 - DevFee * 0.01)) }; if (isDual) { perDeviceSpeeds.Add((secondAlgoType, secondaryCurrentSpeed * (1 - DualDevFee * 0.01))); } perDeviceSpeedInfo.Add(uuid, perDeviceSpeeds); // no power usage info perDevicePowerInfo.Add(uuid, -1); } totalSpeed.Add((firstAlgoType, primaryTotalSpeed * (1 - DevFee * 0.01))); if (isDual) { totalSpeed.Add((secondAlgoType, secondaryTotalSpeed * (1 - DualDevFee * 0.01))); } } } } catch (Exception e) { Logger.Error(logGroup, $"Error occured while getting API stats: {e.Message}"); } ad.AlgorithmSpeedsPerDevice = perDeviceSpeedInfo; ad.PowerUsagePerDevice = perDevicePowerInfo; ad.PowerUsageTotal = -1; return(ad); }
private void MinuteCandleByTicks() { // 설정값 var coinName = Coin.Ticker; var candleType = CandleType.Name; var candleCount = CandleCount; var feeRate = FeeRate; var tradeRate = TradeRate; var triggerRate = TriggerRate; // 해당 코인 보유금액이 있으면 매도 없으면 매수 var candles = ApiData.getCandle <List <Candle> >(coinName, candleType, candleCount); // 캔들 조회 var currCandle = candles.First(); // 현재 캔들 var currPrice = currCandle.Close; // 현재가 //var orderChance = GetOrderChance(ApiData, coinName, currPrice); // 주문 가능 정보 var orderChance = new Profit(ApiData, coinName, StartKRW); var krwBalance = orderChance.KRWBalance; // 보유 현금 var coinBalance = orderChance.CoinAmount; // 코인 보유금 var coinVol = orderChance.CoinVol; // 보유 코인 수량 var avgPrice = orderChance.AvgBuyPrice; // 매수 평단가 var minTradeKRW = Settings.Default.minTradeKRW; // 최소 거래 금액 // 분봉 N개를 기준으로 직전 시가 에서 현재 금액 등낙률을 가져온다. var prevCandle = candles[1]; // 직전 캔들 var lastCandle = candles.Last(); // 마지막 캔들 var prevPrice = prevCandle.Close; // 직전종가 prevPrice = prevCandle.Low; // 직전 저가 대입 var startPrice = lastCandle.Open; // 마지막 캔들 시작가 var highPrice = candles.GetRange(1, candles.Count - 1).Max(x => x.High); // 최고가 startPrice = Math.Max(startPrice, highPrice); // 캔들 최고가 대입 var change = (currPrice - prevPrice); // 변동가 var currentRate = (change / currPrice) * 100; // 등락율 var candlesChange = (currPrice - startPrice); // 캔들 변동가 var candlesRate = (candlesChange / startPrice) * 100; // 캔들 등락율 var profit = (avgPrice == 0) ? 0D : (currPrice - avgPrice); // 수익 var tradeProfitRate = (avgPrice == 0) ? 0D : (profit / avgPrice) * 100; // 수익율 var result = null as JObject; var args = new object[] { coinName, currPrice, prevPrice, startPrice, currentRate, candlesRate, avgPrice, tradeProfitRate }; var buyTs = DateTime.Now - LastBuyDate; var sellTs = DateTime.Now - LastSellDate; var minutes = sellTs.TotalMinutes; { txtKRW.Text = krwBalance.ToString("N0"); txtCoinBalance.Text = coinBalance.ToString("N0"); } WriteLog("{0} : 현재가 {1:N0}, 직전가 {2:N0}, 시작가 {3:N0}, 직전등락폭 {4:F6}, 등락폭 {5:F6}, 평단가 {6:N0}, 수익율 {7:F6}", args); if (StartKRW < minTradeKRW && krwBalance > minTradeKRW && coinBalance < minTradeKRW) { // 거래 시작 금액 StartKRW = krwBalance; } try { if (coinBalance <= minTradeKRW && krwBalance <= minTradeKRW) { // 보유현금과 보유 코인이 최소 거래금액 보다 적으면 거래 없음 WriteLog("#### 거래 불가 : 보유현금 {0}, 코인보유금 {1}, 최소 거래 금액 {2},", krwBalance, coinBalance, minTradeKRW); } else if (krwBalance > minTradeKRW && sellTs.TotalSeconds >= CandleType.Minute * 60 / 2 && candlesRate <= -(triggerRate + (feeRate * 2)) && currentRate >= (feeRate * 2)) { // BUY // 보유현금이 최소 거래금액 보다 많음 // 수익율 초과하여 떨어지다 수수료율 2배 이상 상승 했을때 거래비율 만큼 산다. var total = ToOrderPrice(krwBalance); result = React.executeDeal(true, false, coinName, 0, 0, total); LastBuyDate = DateTime.Now; WriteLog("#### {0} BUY : 금액 {1:N0}, 수량 {2:F6}", coinName, total, total / currPrice); } else if (coinBalance > minTradeKRW && (buyTs.TotalSeconds >= CandleType.Minute * 60 || tradeProfitRate >= (triggerRate / candleCount) + (feeRate * 2))) { // SELL // 코인평가금 최소 거래금액 보다 많음 // 분봉 하나의 시간이 지나면 시장가에 전체 매도 // 현재가가 평단가 보다 (수익율/캔들수 + 수료율2배) 이상일때 전체 매도 var vol = coinVol; vol = Math.Truncate(vol * 100000) / 100000; result = React.executeDeal(false, false, coinName, vol, 0, 0); LastSellDate = DateTime.Now; WriteLog("#### {0} SELL : 금액 {1:N0}, 수량 {2:F6}", coinName, vol * currPrice, vol); } } catch (Exception ex) { WriteLog(ex.StackTrace); } if (result != null) { WriteLog("#### RESULT : {0}", result.ToString()); var coinProfit = new Profit(ApiData, coinName, StartKRW); var profits = new object[] { coinName, StartKRW, coinProfit.TotalKrw, coinProfit.KrwProfit, coinProfit.KrwProfitRate }; txtProfitPrice.Text = coinProfit.KrwProfit.ToString("N0"); txtProfitRate.Text = coinProfit.KrwProfitRate.ToString("F6"); WriteLog("#### {0} 수익 : 거래시작금액 {1:N0}, 현재평가 금액 {2:N0}, 수익금액 {3:N0}, 수익율 {4:F6}", profits); } }
public override async Task <ApiData> GetSummaryAsync() { CurrentMinerReadStatus = MinerApiReadStatus.NONE; var ad = new ApiData(MiningSetup.CurrentAlgorithmType, MiningSetup.CurrentSecondaryAlgorithmType); double tmp = 0; string resp = null; try { var bytesToSend = Encoding.ASCII.GetBytes("summary"); var client = new TcpClient("127.0.0.1", ApiPort); var nwStream = client.GetStream(); await nwStream.WriteAsync(bytesToSend, 0, bytesToSend.Length); var bytesToRead = new byte[client.ReceiveBufferSize]; var bytesRead = await nwStream.ReadAsync(bytesToRead, 0, client.ReceiveBufferSize); var respStr = Encoding.ASCII.GetString(bytesToRead, 0, bytesRead); client.Close(); resp = respStr; } catch (Exception ex) { Helpers.ConsolePrint(MinerTag(), "GetSummary exception: " + ex.Message); } if (resp != null) { var st = resp.IndexOf(";KHS="); var e = resp.IndexOf(";SOLV="); var parse = resp.Substring(st + 5, e - st - 5).Trim(); try { tmp = Double.Parse(parse, CultureInfo.InvariantCulture); } catch { MessageBox.Show("Unsupported miner version - " + MiningSetup.MinerPath, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); BenchmarkSignalFinnished = true; } ad.Speed = tmp * 1000; if (ad.Speed == 0) { CurrentMinerReadStatus = MinerApiReadStatus.READ_SPEED_ZERO; } else { CurrentMinerReadStatus = MinerApiReadStatus.GOT_READ; } if (ad.Speed < 0) { Helpers.ConsolePrint(MinerTag(), "Reporting negative speeds will restart..."); Restart(); } } return(ad); }
public async override Task <ApiData> GetMinerStatsDataAsync() { // lazy init if (_httpClient == null) { _httpClient = new HttpClient(); } var ad = new ApiData(); try { var result = await _httpClient.GetStringAsync($"http://127.0.0.1:{_apiPort}/stat"); ad.ApiResponse = result; var summary = JsonConvert.DeserializeObject <JsonApiResponse>(result); var gpus = _miningPairs.Select(pair => pair.Device); var perDeviceSpeedInfo = new Dictionary <string, IReadOnlyList <(AlgorithmType type, double speed)> >(); var perDevicePowerInfo = new Dictionary <string, int>(); var totalSpeed = 0d; var totalSpeed2 = 0d; var totalPowerUsage = 0; foreach (var gpu in gpus) { var currentDevStats = summary.devices.Where(devStats => devStats.gpu_id == _mappedDeviceIds[gpu.UUID]).FirstOrDefault(); if (currentDevStats == null) { continue; } totalSpeed += currentDevStats.speed; totalSpeed2 += currentDevStats.speed2; if (_algorithmSecondType == AlgorithmType.NONE) { perDeviceSpeedInfo.Add(gpu.UUID, new List <(AlgorithmType type, double speed)>() { (_algorithmType, currentDevStats.speed * (1 - DevFee * 0.01)) }); } else { // only one dual algo here perDeviceSpeedInfo.Add(gpu.UUID, new List <(AlgorithmType type, double speed)>() { (_algorithmType, currentDevStats.speed * (1 - 3.0 * 0.01)), (_algorithmSecondType, currentDevStats.speed2 * (1 - DevFee * 0.01)) }); } var kPower = currentDevStats.power_usage * 1000; totalPowerUsage += kPower; perDevicePowerInfo.Add(gpu.UUID, kPower); } ad.PowerUsageTotal = totalPowerUsage; ad.AlgorithmSpeedsPerDevice = perDeviceSpeedInfo; ad.PowerUsagePerDevice = perDevicePowerInfo; } catch (Exception e) { Logger.Error(_logGroup, $"Error occured while getting API stats: {e.Message}"); //CurrentMinerReadStatus = MinerApiReadStatus.NETWORK_EXCEPTION; } return(ad); }
/// <summary> /// Converts the builder to ApiData and gets the object, which will be the base of the sent Transloadit request /// </summary> /// <returns>Data to be sent to Transloadit backend</returns> public ApiData ToApiData() { ApiData apiData = new ApiData(); apiData.Files = files; apiData.Fields.Add("params", ToJsonString()); foreach (KeyValuePair<string, object> field in fields) { apiData.Fields.Add(field.Key, field.Value); } return apiData; }
void StartSortie(ApiData rpData) { var rSortie = SortieInfo.Current; var rMap = rSortie.Map; r_CurrentSortieID = rSortie.ID; using (var rTransaction = Connection.BeginTransaction()) { using (var rCommand = Connection.CreateCommand()) { rCommand.CommandText = "INSERT OR IGNORE INTO sortie_map(id, is_event_map) VALUES(@map_id, @is_event_map);" + "INSERT INTO sortie(id, map) VALUES(@sortie_id, @map_id);"; rCommand.Parameters.AddWithValue("@map_id", rMap.ID); rCommand.Parameters.AddWithValue("@sortie_id", rSortie.ID); rCommand.Parameters.AddWithValue("@is_event_map", rMap.IsEventMap); rCommand.ExecuteNonQuery(); } rTransaction.Commit(); } InsertExplorationRecord(rSortie); }
internal protected CombinedFleetNightNormalStage(BattleInfo rpOwner, ApiData rpData) : base(rpOwner) { var rRawData = rpData.Data as RawCombinedFleetNight; Shelling = new ShellingPhase(this, rRawData.Shelling, true); }
private static bool TryGetApiData(ImmutableArray<AdditionalText> additionalTexts, CancellationToken cancellationToken, out ApiData shippedData, out ApiData unshippedData) { AdditionalText shippedText; AdditionalText unshippedText; if (!TryGetApiText(additionalTexts, cancellationToken, out shippedText, out unshippedText)) { shippedData = default(ApiData); unshippedData = default(ApiData); return false; } shippedData = ReadApiData(ShippedFileName, shippedText.GetText(cancellationToken)); unshippedData = ReadApiData(UnshippedFileName, unshippedText.GetText(cancellationToken)); return true; }
public async override Task <ApiData> GetMinerStatsDataAsync() { var api = new ApiData(); var elapsedSeconds = DateTime.UtcNow.Subtract(_started).Seconds; if (elapsedSeconds < 10) { return(api); } var perDeviceSpeedInfo = new Dictionary <string, IReadOnlyList <AlgorithmTypeSpeedPair> >(); var perDevicePowerInfo = new Dictionary <string, int>(); var totalSpeed = 0d; var totalPowerUsage = 0; try { JsonApiResponse resp = null; using (var client = new TcpClient("127.0.0.1", _apiPort)) using (var nwStream = client.GetStream()) { var bytesToSend = Encoding.ASCII.GetBytes("{\"id\":\"0\", \"method\":\"getstat\"}\\n"); await nwStream.WriteAsync(bytesToSend, 0, bytesToSend.Length); var bytesToRead = new byte[client.ReceiveBufferSize]; var bytesRead = await nwStream.ReadAsync(bytesToRead, 0, client.ReceiveBufferSize); var respStr = Encoding.ASCII.GetString(bytesToRead, 0, bytesRead); resp = JsonConvert.DeserializeObject <JsonApiResponse>(respStr); client.Close(); } // return if we got nothing var respOK = resp != null && resp.error == null; if (respOK == false) { return(api); } var results = resp.result; var gpus = _miningPairs.Select(pair => pair.Device).Cast <CUDADevice>(); foreach (var gpu in gpus) { var currentDevStats = results.Where(r => int.Parse(r.busid.Split(':')[1], System.Globalization.NumberStyles.HexNumber) == gpu.PCIeBusID).FirstOrDefault(); if (currentDevStats == null) { continue; } totalSpeed += currentDevStats.speed_sps; perDeviceSpeedInfo.Add(gpu.UUID, new List <AlgorithmTypeSpeedPair>() { new AlgorithmTypeSpeedPair(_algorithmType, currentDevStats.speed_sps * (1 - DevFee * 0.01)) }); totalPowerUsage += (int)currentDevStats.gpu_power_usage; perDevicePowerInfo.Add(gpu.UUID, (int)currentDevStats.gpu_power_usage); } } catch (Exception e) { Logger.Error(_logGroup, $"Error occured while getting API stats: {e.Message}"); } api.AlgorithmSpeedsTotal = new List <AlgorithmTypeSpeedPair> { new AlgorithmTypeSpeedPair(_algorithmType, totalSpeed * (1 - DevFee * 0.01)) }; api.PowerUsageTotal = totalPowerUsage; api.AlgorithmSpeedsPerDevice = perDeviceSpeedInfo; api.PowerUsagePerDevice = perDevicePowerInfo; return(api); }
private void MinuteCandleByTicks() { // 설정값 var coinName = Coin.Ticker; var candleType = CandleType.Name; var candleCount = CandleCount; var feeRate = FeeRate; var tradeRate = TradeRate; var triggerRate = TriggerRate; // 캔들 갯수 많큼 캔들 가져오기 var candles = ApiData.getCandle <List <Candle> >(coinName, candleType, candleCount * 2); // 캔들 조회 (2배로 여유롭게) var currPrice = candles.First().Close; // 현재가 var prevPrice = candles[1].Close; // 직전종가 var highPrice = candles.GetRange(1, candleCount - 1).Max(x => x.High); // 최고가 var downPrice = highPrice * (triggerRate + (feeRate * 2)) / 100; // 하락가 var triggerDownPrice = highPrice - downPrice; // 매수 하락 촉발가 var downRate = Math.Min(0D, (currPrice - highPrice) * 100 / highPrice); // 하락율 var upPrice = prevPrice * ((triggerRate / candleCount) + (feeRate * 2)) / 100; // 반등가 var triggerUpPrice = prevPrice + upPrice; // 매수 반등 촉발가 var upRate = Math.Max(0D, (currPrice - prevPrice) * 100 / prevPrice); // 반등 상승율 var downUpRate = upRate == 0 ? 0D : (-downRate / upRate); // 반등율 // 보유현금 및 주문 정보 var orderChance = ApiData.getOrdersChance(coinName); // 주문 가능 정보 var bid = orderChance["bid_account"]; var ask = orderChance["ask_account"]; var krwBalance = bid.Value <double>("balance"); // 보유 현금 var coinVol = ask.Value <double>("balance"); // 보유 코인 수량 var avgPrice = ask.Value <double>("avg_buy_price"); // 매수 평단가 var bidLock = bid.Value <double>("locked"); // 매수 대기 금액 var coinBuyBalance = avgPrice * coinVol; // 코인 매수금 var coinBalance = currPrice * coinVol; // 코인 평가금 var totalBalance = krwBalance + coinBalance; // 현재 자산 var minTradeKRW = Settings.Default.minTradeKRW; // 최소 거래 금액 // var buyTs = DateTime.Now - LastBuyDate; var sellTs = DateTime.Now - LastSellDate; var sellSpan = CandleType.Minute * 60 * candleCount / 3 * 2; // 매도 유예 시간 (초) var sellSec = sellSpan - buyTs.TotalSeconds; // 매도 까지 남은 시간 (초) var targetRate = ((triggerRate / (candleCount - 1)) + (feeRate * 2)) / 100; // 목표 수익율 var targetSellPrice = avgPrice + (avgPrice * targetRate); // 매도 목표가 var result = null as JObject; var args = new object[] { DateTime.Now, coinName, currPrice, prevPrice, highPrice, downRate, upRate, avgPrice, StartKRW, totalBalance, triggerDownPrice, triggerUpPrice, targetSellPrice, sellSec }; log.Debug(JsonConvert.SerializeObject(candles)); log.Debug(JsonConvert.SerializeObject(orderChance)); string format = "[{0:T}] {1} : 현재가 {2:N0}, 직전가 {3:N0}, 최고가 {4:N0}, 하락율 {5:F6}, 반등율 {6:F6}, 평단가 {7:N0}"; format += (coinBalance >= minTradeKRW) ? ", 매도 까지 남은 시간(초) {13:N0}" : ""; format += "\r\n[{0:T}] {1} : 시작자산 {8:N0}, 현재자산 {9:N0} 매수 하락 촉발가 {10:N0}, 매수 반등 촉발가 {11:N0}, 매도 목표가 {12:N0}"; WriteCurrent(format, args); if (StartKRW < minTradeKRW && krwBalance > minTradeKRW && coinBalance < minTradeKRW) { // 거래 시작 금액 StartKRW = krwBalance; } txtKRWBalance.Text = krwBalance.ToString("N0"); txtCoinBalance.Text = coinBalance.ToString("N0"); txtBalance.Text = totalBalance.ToString("N0"); txtStartKRW.Text = StartKRW.ToString("N0"); var buySates = null as string; var sellSates = null as string; try { if (coinBalance <= minTradeKRW && krwBalance <= minTradeKRW) { // 보유현금과 보유 코인이 최소 거래금액 보다 적으면 거래 없음 WriteLog("#### 거래 불가 : 보유현금 {0}, 코인보유금 {1}, 최소 거래 금액 {2},", krwBalance, coinBalance, minTradeKRW); } else if (krwBalance > minTradeKRW && // 보유 현금이 최소거래 금액 보다 크고 sellTs.TotalSeconds >= CandleType.Minute * 60 / 2 && // 매도 이후 분봉의 절반이상이 지나고 currPrice <= Math.Truncate(triggerDownPrice) && currPrice >= Math.Truncate(triggerUpPrice) && // 현재가가 촉발 금액 사이에서 반등하고 downUpRate <= candleCount * 2) // 반등율이 캔들갯수의 2배수가 넘지 않아야 함 { // BUY var total = ToOrderPrice(krwBalance); var avgBuyPrice = currPrice; result = React.executeDeal(true, false, coinName, 0, 0, total); buySates = result.Value <string>("state"); if ("cancel".Equals(buySates)) { System.Threading.Thread.Sleep(1000); result = React.executeDeal(true, false, coinName, 0, 0, total); buySates = result.Value <string>("state"); } } else if (coinBalance > minTradeKRW && // 코인 보유금이 최소거래 금액 보다 크고 (sellSec <= 0D || // 매도 이후 분봉의 3분2 이상이 지나거나 currPrice >= Math.Truncate(targetSellPrice))) // 현재가가 평단가 보다 (수익율/캔들수-1) + 수료율2배 이상일때 전체 매도 { // SELL // 현재가가 평단가 보다 (수익율/캔들수 + 수료율2배) 이상일때 전체 매도 var vol = coinVol; vol = Math.Truncate(vol * 100000) / 100000; result = React.executeDeal(false, false, coinName, vol, 0, 0); sellSates = result.Value <string>("state"); } if (result != null) { WriteLog("{0} RESULT : {1}", coinName, JsonConvert.SerializeObject(result)); } } catch (Exception ex) { WriteLog(ex.StackTrace); } if (result != null && !"cancel".Equals(buySates)) { var uuid = result.Value <string>("uuid"); var side = result.Value <string>("side"); WriteLog("#### START GetOrderResultAsync : {0}", uuid); //result = GetOrderResultAsync(uuid); result = GetOrderResult(uuid); WriteLog("#### FINISH GetOrderResultAsync : {0}", uuid); if (result == null) { WriteLog("#### 거래 결과를 가져올수 없습니다."); return; } var state = result.Value <string>("state"); var price = result.Value <double?>("price") ?? 0D; var volume = result.Value <double?>("volume") ?? 0D; var tradeCount = result.Value <double>("trade_count"); var trades = result["trades"] as JArray; var tradePrice = trades[0].Value <double>("price"); var tradeVolume = trades[0].Value <double>("volume"); var tradeFunds = trades[0].Value <double>("funds"); args = new object[] { uuid, side, state, price, volume, tradeCount, tradePrice, tradeVolume, tradeFunds }; WriteLog("#### uuid {0}, side {1}, state {2}, price {3:N0}, volume {4:F6}, tradeCount {5:N0}, tradePrice {6:N0}, tradeVolume {7:N0}, tradeFunds {8:N0}", args); if ("bid".Equals(side)) { // BUY LastBuyDate = DateTime.Now; WriteLog("#### {0} BUY : 매수금 {1:N0} : 매수 평단가 {1:N0} : 수량 {3:F6}", coinName, price * volume, price, volume); } else if ("ask".Equals(side)) { // SELL LastSellDate = DateTime.Now; WriteLog("#### {0} SELL : 매도금 {1:N0} : 매도 평단가 {1:N0} : 수량 {3:F6}", coinName, price * volume, price, volume); } // 수익 var balance = GetBalance(coinName); krwBalance = balance.KRWBalance; coinBalance = currPrice * balance.CoinVol; totalBalance = krwBalance + coinBalance; var profit = totalBalance - StartKRW; var profitRate = (StartKRW == 0) ? 0D : profit / StartKRW * 100; txtKRWBalance.Text = krwBalance.ToString("N0"); txtCoinBalance.Text = coinBalance.ToString("N0"); txtBalance.Text = totalBalance.ToString("N0"); txtProfitPrice.Text = profit.ToString("N0"); txtProfitRate.Text = profitRate.ToString("F4"); args = new object[] { coinName, StartKRW, totalBalance, profit, profitRate, krwBalance, coinBalance }; WriteLog("#### {0} 수익 : 거래시작금액 {1:N0}, 현재평가 금액 {2:N0}, 수익금액 {3:N0}, 수익율 {4:F6}, 보유현금 {5:N0}, 코인 평가 {6:N0}", args); } }
protected void OnProcessSucceeded(ApiData rpData) => ProcessSucceeded.OnNext(rpData);