Search in sources :

Example 11 with RecommendedLoan

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.");
    }
}
Also used : RecommendedLoan(com.github.robozonky.api.strategies.RecommendedLoan) ExecutionCompletedEvent(com.github.robozonky.api.notifications.ExecutionCompletedEvent) TransactionCategory(com.github.robozonky.api.remote.enums.TransactionCategory) LoggerFactory(org.slf4j.LoggerFactory) InvestmentDelegatedEvent(com.github.robozonky.api.notifications.InvestmentDelegatedEvent) ControlApi(com.github.robozonky.api.remote.ControlApi) FastList(org.eclipse.collections.impl.list.mutable.FastList) ArrayList(java.util.ArrayList) BlockedAmount(com.github.robozonky.api.remote.entities.BlockedAmount) Events(com.github.robozonky.app.Events) Authenticated(com.github.robozonky.app.authentication.Authenticated) Defaults(com.github.robozonky.internal.api.Defaults) ConfirmationProvider(com.github.robozonky.api.confirmations.ConfirmationProvider) InvestmentRejectedEvent(com.github.robozonky.api.notifications.InvestmentRejectedEvent) LoanDescriptor(com.github.robozonky.api.strategies.LoanDescriptor) Logger(org.slf4j.Logger) Collection(java.util.Collection) ExecutionStartedEvent(com.github.robozonky.api.notifications.ExecutionStartedEvent) Collectors(java.util.stream.Collectors) Event(com.github.robozonky.api.notifications.Event) List(java.util.List) InvestmentRequestedEvent(com.github.robozonky.api.notifications.InvestmentRequestedEvent) PortfolioOverview(com.github.robozonky.api.strategies.PortfolioOverview) Investment(com.github.robozonky.api.remote.entities.sanitized.Investment) InvestmentMadeEvent(com.github.robozonky.api.notifications.InvestmentMadeEvent) InvestmentSkippedEvent(com.github.robozonky.api.notifications.InvestmentSkippedEvent) Portfolio(com.github.robozonky.app.portfolio.Portfolio) Collections(java.util.Collections) LoanRecommendedEvent(com.github.robozonky.api.notifications.LoanRecommendedEvent) InvestmentDelegatedEvent(com.github.robozonky.api.notifications.InvestmentDelegatedEvent) LoanDescriptor(com.github.robozonky.api.strategies.LoanDescriptor) InvestmentRequestedEvent(com.github.robozonky.api.notifications.InvestmentRequestedEvent) ExecutionCompletedEvent(com.github.robozonky.api.notifications.ExecutionCompletedEvent) InvestmentDelegatedEvent(com.github.robozonky.api.notifications.InvestmentDelegatedEvent) InvestmentRejectedEvent(com.github.robozonky.api.notifications.InvestmentRejectedEvent) ExecutionStartedEvent(com.github.robozonky.api.notifications.ExecutionStartedEvent) Event(com.github.robozonky.api.notifications.Event) InvestmentRequestedEvent(com.github.robozonky.api.notifications.InvestmentRequestedEvent) InvestmentMadeEvent(com.github.robozonky.api.notifications.InvestmentMadeEvent) InvestmentSkippedEvent(com.github.robozonky.api.notifications.InvestmentSkippedEvent) LoanRecommendedEvent(com.github.robozonky.api.notifications.LoanRecommendedEvent) InvestmentSkippedEvent(com.github.robozonky.api.notifications.InvestmentSkippedEvent) InvestmentRejectedEvent(com.github.robozonky.api.notifications.InvestmentRejectedEvent) Investment(com.github.robozonky.api.remote.entities.sanitized.Investment) InvestmentMadeEvent(com.github.robozonky.api.notifications.InvestmentMadeEvent)

Example 12 with RecommendedLoan

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);
}
Also used : RecommendedLoan(com.github.robozonky.api.strategies.RecommendedLoan) DynamicTest(org.junit.jupiter.api.DynamicTest)

Example 13 with RecommendedLoan

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);
    });
}
Also used : Authenticated(com.github.robozonky.app.authentication.Authenticated) RecommendedLoan(com.github.robozonky.api.strategies.RecommendedLoan) Portfolio(com.github.robozonky.app.portfolio.Portfolio) LoanDescriptor(com.github.robozonky.api.strategies.LoanDescriptor) Zonky(com.github.robozonky.common.remote.Zonky) ExecutionCompletedEvent(com.github.robozonky.api.notifications.ExecutionCompletedEvent) InvestmentDelegatedEvent(com.github.robozonky.api.notifications.InvestmentDelegatedEvent) InvestmentRejectedEvent(com.github.robozonky.api.notifications.InvestmentRejectedEvent) ExecutionStartedEvent(com.github.robozonky.api.notifications.ExecutionStartedEvent) Event(com.github.robozonky.api.notifications.Event) InvestmentRequestedEvent(com.github.robozonky.api.notifications.InvestmentRequestedEvent) InvestmentMadeEvent(com.github.robozonky.api.notifications.InvestmentMadeEvent) InvestmentSkippedEvent(com.github.robozonky.api.notifications.InvestmentSkippedEvent) LoanRecommendedEvent(com.github.robozonky.api.notifications.LoanRecommendedEvent) AbstractZonkyLeveragingTest(com.github.robozonky.app.AbstractZonkyLeveragingTest) Test(org.junit.jupiter.api.Test)

Example 14 with RecommendedLoan

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();
}
Also used : Authenticated(com.github.robozonky.app.authentication.Authenticated) RecommendedLoan(com.github.robozonky.api.strategies.RecommendedLoan) Portfolio(com.github.robozonky.app.portfolio.Portfolio) ExecutionCompletedEvent(com.github.robozonky.api.notifications.ExecutionCompletedEvent) InvestmentDelegatedEvent(com.github.robozonky.api.notifications.InvestmentDelegatedEvent) InvestmentRejectedEvent(com.github.robozonky.api.notifications.InvestmentRejectedEvent) ExecutionStartedEvent(com.github.robozonky.api.notifications.ExecutionStartedEvent) Event(com.github.robozonky.api.notifications.Event) InvestmentRequestedEvent(com.github.robozonky.api.notifications.InvestmentRequestedEvent) InvestmentMadeEvent(com.github.robozonky.api.notifications.InvestmentMadeEvent) InvestmentSkippedEvent(com.github.robozonky.api.notifications.InvestmentSkippedEvent) LoanRecommendedEvent(com.github.robozonky.api.notifications.LoanRecommendedEvent) Zonky(com.github.robozonky.common.remote.Zonky) AbstractZonkyLeveragingTest(com.github.robozonky.app.AbstractZonkyLeveragingTest) Test(org.junit.jupiter.api.Test)

Example 15 with RecommendedLoan

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);
}
Also used : Authenticated(com.github.robozonky.app.authentication.Authenticated) RecommendedLoan(com.github.robozonky.api.strategies.RecommendedLoan) Portfolio(com.github.robozonky.app.portfolio.Portfolio) Zonky(com.github.robozonky.common.remote.Zonky) ExecutionCompletedEvent(com.github.robozonky.api.notifications.ExecutionCompletedEvent) InvestmentDelegatedEvent(com.github.robozonky.api.notifications.InvestmentDelegatedEvent) InvestmentRejectedEvent(com.github.robozonky.api.notifications.InvestmentRejectedEvent) ExecutionStartedEvent(com.github.robozonky.api.notifications.ExecutionStartedEvent) Event(com.github.robozonky.api.notifications.Event) InvestmentRequestedEvent(com.github.robozonky.api.notifications.InvestmentRequestedEvent) InvestmentMadeEvent(com.github.robozonky.api.notifications.InvestmentMadeEvent) InvestmentSkippedEvent(com.github.robozonky.api.notifications.InvestmentSkippedEvent) LoanRecommendedEvent(com.github.robozonky.api.notifications.LoanRecommendedEvent) Investment(com.github.robozonky.api.remote.entities.sanitized.Investment) InvestmentMadeEvent(com.github.robozonky.api.notifications.InvestmentMadeEvent) AbstractZonkyLeveragingTest(com.github.robozonky.app.AbstractZonkyLeveragingTest) Test(org.junit.jupiter.api.Test)

Aggregations

RecommendedLoan (com.github.robozonky.api.strategies.RecommendedLoan)18 Test (org.junit.jupiter.api.Test)15 LoanDescriptor (com.github.robozonky.api.strategies.LoanDescriptor)12 InvestmentDelegatedEvent (com.github.robozonky.api.notifications.InvestmentDelegatedEvent)11 InvestmentMadeEvent (com.github.robozonky.api.notifications.InvestmentMadeEvent)11 InvestmentRejectedEvent (com.github.robozonky.api.notifications.InvestmentRejectedEvent)11 Event (com.github.robozonky.api.notifications.Event)10 ExecutionCompletedEvent (com.github.robozonky.api.notifications.ExecutionCompletedEvent)10 ExecutionStartedEvent (com.github.robozonky.api.notifications.ExecutionStartedEvent)9 InvestmentSkippedEvent (com.github.robozonky.api.notifications.InvestmentSkippedEvent)9 Authenticated (com.github.robozonky.app.authentication.Authenticated)9 Portfolio (com.github.robozonky.app.portfolio.Portfolio)9 InvestmentRequestedEvent (com.github.robozonky.api.notifications.InvestmentRequestedEvent)8 LoanRecommendedEvent (com.github.robozonky.api.notifications.LoanRecommendedEvent)8 PortfolioOverview (com.github.robozonky.api.strategies.PortfolioOverview)8 AbstractZonkyLeveragingTest (com.github.robozonky.app.AbstractZonkyLeveragingTest)8 Zonky (com.github.robozonky.common.remote.Zonky)8 Restrictions (com.github.robozonky.api.remote.entities.Restrictions)5 Investment (com.github.robozonky.api.remote.entities.sanitized.Investment)5 Loan (com.github.robozonky.api.remote.entities.sanitized.Loan)5