use of com.github.robozonky.api.strategies.RecommendedLoan in project robozonky by RoboZonky.
the class Session method invest.
/**
* Request {@link ControlApi} to invest in a given loan, leveraging the {@link ConfirmationProvider}.
* @param recommendation Loan to invest into.
* @return True if investment successful. The investment is reflected in {@link #getResult()}.
*/
public boolean invest(final RecommendedLoan recommendation) {
final LoanDescriptor loan = recommendation.descriptor();
final int loanId = loan.item().getId();
if (portfolioOverview.getCzkAvailable() < recommendation.amount().intValue()) {
// should not be allowed by the calling code
return false;
}
Events.fire(new InvestmentRequestedEvent(recommendation));
final boolean seenBefore = state.getSeenLoans().stream().anyMatch(l -> isSameLoan(l, loanId));
final ZonkyResponse response = investor.invest(recommendation, seenBefore);
Session.LOGGER.debug("Response for loan {}: {}.", loanId, response);
final String providerId = investor.getConfirmationProviderId().orElse("-");
switch(response.getType()) {
case REJECTED:
return investor.getConfirmationProviderId().map(c -> {
Events.fire(new InvestmentRejectedEvent(recommendation, providerId));
// rejected through a confirmation provider => forget
discard(loan);
return false;
}).orElseGet(() -> {
// rejected due to no confirmation provider => make available for direct investment later
Events.fire(new InvestmentSkippedEvent(recommendation));
Session.LOGGER.debug("Loan #{} protected by CAPTCHA, will check back later.", loanId);
skip(loan);
return false;
});
case DELEGATED:
final Event e = new InvestmentDelegatedEvent(recommendation, providerId);
Events.fire(e);
if (recommendation.isConfirmationRequired()) {
// confirmation required, delegation successful => forget
discard(loan);
} else {
// confirmation not required, delegation successful => make available for direct investment later
skip(loan);
}
return false;
case INVESTED:
final int confirmedAmount = response.getConfirmedAmount().getAsInt();
final Investment i = Investment.fresh(recommendation.descriptor().item(), confirmedAmount);
markSuccessfulInvestment(i);
Events.fire(new InvestmentMadeEvent(i, loan.item(), portfolioOverview));
return true;
case // still protected by CAPTCHA
SEEN_BEFORE:
return false;
default:
throw new IllegalStateException("Not possible.");
}
}
use of com.github.robozonky.api.strategies.RecommendedLoan in project robozonky by RoboZonky.
the class InvestorTest method forPossibility.
private DynamicNode forPossibility(final ProxyType proxyType, final Captcha captcha, final Remote confirmation, final RemoteResponse confirmationResponse, final ZonkyResponseType responseType) {
final RecommendedLoan recommendedLoan = getRecommendation(confirmation, captcha);
final DynamicTest seenBefore = dynamicTest("seen before", () -> testBeforeSeen(proxyType, confirmationResponse, responseType, recommendedLoan));
final DynamicTest notSeenBefore = dynamicTest("never seen", () -> testNeverSeen(proxyType, confirmationResponse, responseType, recommendedLoan));
final Stream<DynamicTest> tests = isValidForLoansSeenBefore(responseType) ? Stream.of(seenBefore, notSeenBefore) : Stream.of(notSeenBefore);
final String containerName = proxyType + "+" + captcha + "+" + confirmation + "+" + confirmation + "=" + responseType;
return dynamicContainer(containerName, tests);
}
use of com.github.robozonky.api.strategies.RecommendedLoan in project robozonky by RoboZonky.
the class SessionTest method investmentIgnoredWhenNoConfirmationProviderAndCaptcha.
@Test
void investmentIgnoredWhenNoConfirmationProviderAndCaptcha() {
final LoanDescriptor ld = AbstractZonkyLeveragingTest.mockLoanDescriptor();
final RecommendedLoan r = ld.recommend(200).get();
final Collection<LoanDescriptor> availableLoans = Collections.singletonList(ld);
// setup APIs
final Zonky z = AbstractZonkyLeveragingTest.harmlessZonky(10_000);
final Authenticated auth = mockAuthentication(z);
final Investor p = mock(Investor.class);
doReturn(new ZonkyResponse(ZonkyResponseType.REJECTED)).when(p).invest(eq(r), anyBoolean());
doReturn(Optional.empty()).when(p).getConfirmationProviderId();
final Portfolio portfolio = Portfolio.create(z, mockBalance(z));
final Session t = new Session(portfolio, new LinkedHashSet<>(availableLoans), p, auth);
final boolean result = t.invest(r);
assertThat(result).isFalse();
// validate event
final List<Event> newEvents = this.getNewEvents();
assertThat(newEvents).hasSize(2);
assertSoftly(softly -> {
softly.assertThat(newEvents.get(0)).isInstanceOf(InvestmentRequestedEvent.class);
softly.assertThat(newEvents.get(1)).isInstanceOf(InvestmentSkippedEvent.class);
});
}
use of com.github.robozonky.api.strategies.RecommendedLoan in project robozonky by RoboZonky.
the class SessionTest method underBalance.
@Test
void underBalance() {
// setup APIs
final Zonky z = AbstractZonkyLeveragingTest.harmlessZonky(Defaults.MINIMUM_INVESTMENT_IN_CZK - 1);
final Authenticated auth = mockAuthentication(z);
final Portfolio portfolio = Portfolio.create(z, mockBalance(z));
// run test
final Session it = new Session(portfolio, Collections.emptySet(), getInvestor(auth), auth);
final Optional<RecommendedLoan> recommendation = AbstractZonkyLeveragingTest.mockLoanDescriptor().recommend(BigDecimal.valueOf(Defaults.MINIMUM_INVESTMENT_IN_CZK));
final boolean result = it.invest(recommendation.get());
// verify result
assertThat(result).isFalse();
final List<Event> newEvents = this.getNewEvents();
assertThat(newEvents).isEmpty();
}
use of com.github.robozonky.api.strategies.RecommendedLoan in project robozonky by RoboZonky.
the class SessionTest method investmentSuccessful.
@Test
void investmentSuccessful() {
final int oldBalance = 10_000;
final int amountToInvest = 200;
final RecommendedLoan r = AbstractZonkyLeveragingTest.mockLoanDescriptor().recommend(amountToInvest).get();
final Zonky z = AbstractZonkyLeveragingTest.harmlessZonky(oldBalance);
when(z.getLoan(eq(r.descriptor().item().getId()))).thenReturn(r.descriptor().item());
final Authenticated auth = mockAuthentication(z);
final Investor p = mock(Investor.class);
doReturn(new ZonkyResponse(amountToInvest)).when(p).invest(eq(r), anyBoolean());
doReturn(Optional.of("something")).when(p).getConfirmationProviderId();
final Portfolio portfolio = Portfolio.create(z, mockBalance(z));
final Session t = new Session(portfolio, Collections.emptySet(), p, auth);
final boolean result = t.invest(r);
assertThat(result).isTrue();
final List<Investment> investments = t.getResult();
assertThat(investments).hasSize(1);
assertThat(investments.get(0).getOriginalPrincipal().intValue()).isEqualTo(amountToInvest);
// validate event sequence
final List<Event> newEvents = this.getNewEvents();
assertThat(newEvents).hasSize(2);
assertSoftly(softly -> {
softly.assertThat(newEvents.get(0)).isInstanceOf(InvestmentRequestedEvent.class);
softly.assertThat(newEvents.get(1)).isInstanceOf(InvestmentMadeEvent.class);
});
// validate event contents
final InvestmentMadeEvent e = (InvestmentMadeEvent) newEvents.get(1);
assertThat(e.getPortfolioOverview().getCzkAvailable()).isEqualTo(oldBalance - amountToInvest);
}
Aggregations